ignore TARGET environment variable (Makefiles tend to set that and confuse cparser)
[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 static ir_entity *underscore_compilerlib_entity_creator(ident *id, ir_type *mt)
18 {
19         ir_entity *entity = new_entity(get_glob_type(), id, mt);
20         ident     *ldname = id_mangle3("_", id, "");
21
22         set_entity_visibility(entity, ir_visibility_external);
23         set_entity_ld_ident(entity, ldname);
24
25         return entity;
26 }
27
28 /**
29  * Initialize firm codegeneration for a specific operating system.
30  * The argument is the operating system part of a target-triple
31  */
32 static bool setup_os_support(const char *os)
33 {
34         if (strstr(os, "linux") != NULL || strstr(os, "bsd") != NULL
35                         || streq(os, "solaris")) {
36                 set_be_option("ia32-gasmode=elf");
37         } else if (strstart(os, "darwin")) {
38                 set_be_option("ia32-gasmode=macho");
39                 set_be_option("ia32-stackalign=4");
40                 set_be_option("pic=true");
41                 set_compilerlib_entity_creator(underscore_compilerlib_entity_creator);
42         } else if (strstr(os, "mingw") != NULL || streq(os, "win32")) {
43                 set_be_option("ia32-gasmode=mingw");
44                 set_compilerlib_entity_creator(underscore_compilerlib_entity_creator);
45         } else {
46                 return false;
47         }
48
49         return true;
50 }
51
52 bool setup_firm_for_machine(const machine_triple_t *machine)
53 {
54         const char *cpu = machine->cpu_type;
55
56         if (streq(cpu, "i386")) {
57                 set_be_option("isa=ia32");
58                 set_be_option("ia32-arch=i386");
59         } else if (streq(cpu, "i486")) {
60                 set_be_option("isa=ia32");
61                 set_be_option("ia32-arch=i486");
62         } else if (streq(cpu, "i586")) {
63                 set_be_option("isa=ia32");
64                 set_be_option("ia32-arch=i586");
65         } else if (streq(cpu, "i686")) {
66                 set_be_option("isa=ia32");
67                 set_be_option("ia32-arch=i686");
68         } else if (streq(cpu, "i786")) {
69                 set_be_option("isa=ia32");
70                 set_be_option("ia32-arch=pentium4");
71         } else if (streq(cpu, "x86_64")) {
72                 set_be_option("isa=amd64");
73         } else if (streq(cpu, "sparc")) {
74                 set_be_option("isa=sparc");
75         } else if (streq(cpu, "arm")) {
76                 set_be_option("isa=arm");
77         } else {
78                 fprintf(stderr, "Unknown cpu '%s' in target-triple\n", cpu);
79                 return false;
80         }
81
82         /* process operating system */
83         if (!setup_os_support(machine->operating_system)) {
84                 fprintf(stderr, "Unknown operating system '%s' in target-triple\n", machine->operating_system);
85                 return false;
86         }
87         return true;
88 }
89
90 machine_triple_t *firm_get_host_machine(void)
91 {
92         machine_triple_t *machine = XMALLOC(machine_triple_t);
93         machine->cpu_type = xstrdup("i386");
94         machine->manufacturer = xstrdup("unknown");
95 #if defined(_WIN32) || defined(__CYGWIN__)
96         machine->operating_system = xstrdup("win32");
97 #elif defined(__APPLE__)
98         machine->operating_system = xstrdup("darwin");
99 #else
100         machine->operating_system = xstrdup("linux");
101 #endif
102         return machine;
103 }
104
105 void firm_free_machine_triple(machine_triple_t *machine)
106 {
107         free(machine->cpu_type);
108         free(machine->manufacturer);
109         free(machine->operating_system);
110         free(machine);
111 }
112
113 machine_triple_t *firm_parse_machine_triple(const char *triple_string)
114 {
115         const char *manufacturer = strchr(triple_string, '-');
116         if (manufacturer == NULL) {
117                 return NULL;
118         }
119         manufacturer += 1;
120
121         const char *os = strchr(manufacturer, '-');
122         if (os == NULL) {
123                 return false;
124         }
125         os += 1;
126
127         /* Note: Triples are more or less defined by what the config.guess and
128          * config.sub scripts from GNU autoconf emit. We have to lookup there what
129          * triples are possible */
130
131         const char *cpu = triple_string;
132
133         machine_triple_t *triple = XMALLOCZ(machine_triple_t);
134
135         size_t cpu_type_len = manufacturer-cpu;
136         triple->cpu_type = XMALLOCN(char, cpu_type_len);
137         memcpy(triple->cpu_type, cpu, cpu_type_len-1);
138         triple->cpu_type[cpu_type_len-1] = '\0';
139
140         /* process manufacturer, alot of people incorrectly leave out the
141          * manufacturer instead of using unknown- */
142         if (strstart(manufacturer, "linux")) {
143                 triple->manufacturer = xstrdup("unknown");
144                 os = manufacturer;
145         } else {
146                 size_t manufacturer_len = os-manufacturer;
147                 triple->manufacturer = XMALLOCN(char, manufacturer_len);
148                 memcpy(triple->manufacturer, manufacturer, manufacturer_len-1);
149                 triple->manufacturer[manufacturer_len-1] = '\0';
150         }
151
152         triple->operating_system = xstrdup(os);
153         return triple;
154 }