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