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