Adapted cparser to CopyB lowering changes.
[cparser] / driver / firm_machine.c
1 #include <config.h>
2
3 #include <assert.h>
4 #include <stdbool.h>
5 #include "firm_machine.h"
6 #include "adt/strutil.h"
7 #include "adt/xmalloc.h"
8 #include <libfirm/firm.h>
9
10 static void set_be_option(const char *arg)
11 {
12         int res = be_parse_arg(arg);
13         (void) res;
14         assert(res);
15 }
16
17 /**
18  * Initialize firm codegeneration for a specific operating system.
19  * The argument is the operating system part of a target-triple
20  */
21 static bool setup_os_support(const char *os)
22 {
23         if (strstr(os, "linux") != NULL || strstr(os, "bsd") != NULL
24                         || streq(os, "solaris")) {
25                 set_be_option("ia32-gasmode=elf");
26         } else if (streq(os, "darwin")) {
27                 set_be_option("ia32-gasmode=macho");
28                 set_be_option("ia32-stackalign=4");
29                 set_be_option("pic=true");
30         } else if (strstr(os, "mingw") != NULL || streq(os, "win32")) {
31                 set_be_option("ia32-gasmode=mingw");
32         } else {
33                 return false;
34         }
35
36         return true;
37 }
38
39 bool setup_firm_for_machine(const machine_triple_t *machine)
40 {
41         const char *cpu = machine->cpu_type;
42
43         if (streq(cpu, "i386")) {
44                 set_be_option("isa=ia32");
45                 set_be_option("ia32-arch=i386");
46         } else if (streq(cpu, "i486")) {
47                 set_be_option("isa=ia32");
48                 set_be_option("ia32-arch=i486");
49         } else if (streq(cpu, "i586")) {
50                 set_be_option("isa=ia32");
51                 set_be_option("ia32-arch=i586");
52         } else if (streq(cpu, "i686")) {
53                 set_be_option("isa=ia32");
54                 set_be_option("ia32-arch=i686");
55         } else if (streq(cpu, "i786")) {
56                 set_be_option("isa=ia32");
57                 set_be_option("ia32-arch=pentium4");
58         } else if (streq(cpu, "x86_64")) {
59                 set_be_option("isa=amd64");
60         } else if (streq(cpu, "sparc")) {
61                 set_be_option("isa=sparc");
62         } else if (streq(cpu, "arm")) {
63                 set_be_option("isa=arm");
64         } else {
65                 fprintf(stderr, "Unknown cpu '%s' in target-triple\n", cpu);
66                 return false;
67         }
68
69         /* process operating system */
70         if (!setup_os_support(machine->operating_system)) {
71                 fprintf(stderr, "Unknown operating system '%s' in target-triple\n", machine->operating_system);
72                 return false;
73         }
74         return true;
75 }
76
77 machine_triple_t *firm_get_host_machine(void)
78 {
79         machine_triple_t *machine = XMALLOC(machine_triple_t);
80         machine->cpu_type = xstrdup("i386");
81         machine->manufacturer = xstrdup("unknown");
82 #if defined(_WIN32) || defined(__CYGWIN__)
83         machine->operating_system = xstrdup("win32");
84 #elif defined(__APPLE__)
85         machine->operating_system = xstrdup("darwin");
86 #else
87         machine->operating_system = xstrdup("linux");
88 #endif
89         return machine;
90 }
91
92 void firm_free_machine_triple(machine_triple_t *machine)
93 {
94         free(machine->cpu_type);
95         free(machine->manufacturer);
96         free(machine->operating_system);
97         free(machine);
98 }
99
100 machine_triple_t *firm_parse_machine_triple(const char *triple_string)
101 {
102         const char *manufacturer = strchr(triple_string, '-');
103         if (manufacturer == NULL) {
104                 return NULL;
105         }
106         manufacturer += 1;
107
108         const char *os = strchr(manufacturer, '-');
109         if (os == NULL) {
110                 return false;
111         }
112         os += 1;
113
114         /* Note: Triples are more or less defined by what the config.guess and
115          * config.sub scripts from GNU autoconf emit. We have to lookup there what
116          * triples are possible */
117
118         const char *cpu = triple_string;
119
120         machine_triple_t *triple = XMALLOCZ(machine_triple_t);
121
122         size_t cpu_type_len = manufacturer-cpu;
123         triple->cpu_type = XMALLOCN(char, cpu_type_len);
124         memcpy(triple->cpu_type, cpu, cpu_type_len-1);
125         triple->cpu_type[cpu_type_len-1] = '\0';
126
127         /* process manufacturer, alot of people incorrectly leave out the
128          * manufacturer instead of using unknown- */
129         if (strstart(manufacturer, "linux")) {
130                 triple->manufacturer = xstrdup("unknown");
131                 os = manufacturer;
132         } else {
133                 size_t manufacturer_len = os-manufacturer;
134                 triple->manufacturer = XMALLOCN(char, manufacturer_len);
135                 memcpy(triple->manufacturer, manufacturer, manufacturer_len-1);
136                 triple->manufacturer[manufacturer_len-1] = '\0';
137         }
138
139         triple->operating_system = xstrdup(os);
140         return triple;
141 }