refactor machine/os initialisation part so it can be reused by other frontends
[cparser] / main.c
diff --git a/main.c b/main.c
index 34218ed..ff41e7d 100644 (file)
--- a/main.c
+++ b/main.c
 #include "driver/firm_opt.h"
 #include "driver/firm_cmdline.h"
 #include "driver/firm_timing.h"
+#include "driver/firm_os.h"
 #include "adt/error.h"
+#include "adt/strutil.h"
 #include "wrappergen/write_fluffy.h"
-#include "wrappergen/write_caml.h"
 #include "wrappergen/write_jna.h"
 #include "revision.h"
 #include "warning.h"
 
 #ifndef PREPROCESSOR
 #ifndef __WIN32__
-#define PREPROCESSOR "gcc -E -m32 -U__STRICT_ANSI__"
+#define PREPROCESSOR "gcc -E -U__STRICT_ANSI__"
 #else
-#define PREPROCESSOR "cpp -m32 -U__STRICT_ANSI__"
+#define PREPROCESSOR "cpp -U__STRICT_ANSI__"
 #endif
 #endif
 
 #ifndef LINKER
-#define LINKER    "gcc -m32"
+#define LINKER    "gcc"
 #endif
 
 #ifndef ASSEMBLER
-#ifdef __APPLE__
-#define ASSEMBLER "gcc -m32 -c -xassembler"
-#else
-#define ASSEMBLER "as --32"
-#endif
+#define ASSEMBLER "gcc -c -xassembler"
 #endif
 
 unsigned int       c_mode                    = _C89 | _ANSI | _C99 | _GNUC;
@@ -107,7 +104,6 @@ bool               byte_order_big_endian     = false;
 bool               char_is_signed            = true;
 bool               strict_mode               = false;
 bool               use_builtins              = false;
-bool               have_const_functions      = false;
 atomic_type_kind_t wchar_atomic_kind         = ATOMIC_TYPE_INT;
 unsigned           force_long_double_size    = 0;
 bool               enable_main_collect2_hack = false;
@@ -119,11 +115,14 @@ extern bool print_implicit_casts;
 /* to switch on printing of parenthesis to indicate operator precedence */
 extern bool print_parenthesis;
 
-static const char     *target_triple;
-static int             verbose;
-static struct obstack  cppflags_obst, ldflags_obst;
-static char            dep_target[1024];
-static const char     *outname;
+static machine_triple_t *target_machine;
+static const char       *target_triple;
+static int               verbose;
+static struct obstack    cppflags_obst;
+static struct obstack    ldflags_obst;
+static struct obstack    asflags_obst;
+static char              dep_target[1024];
+static const char       *outname;
 
 typedef enum lang_standard_t {
        STANDARD_DEFAULT, /* gnu99 (for C, GCC does gnu89) or gnu++98 (for C++) */
@@ -335,56 +334,52 @@ static FILE *preprocess(const char *fname, filetype_t filetype)
                }
        }
        add_flag(&cppflags_obst, fname);
-
        obstack_1grow(&cppflags_obst, '\0');
-       char *buf = obstack_finish(&cppflags_obst);
+
+       char *commandline = obstack_finish(&cppflags_obst);
        if (verbose) {
-               puts(buf);
+               puts(commandline);
        }
-
-       FILE *f = popen(buf, "r");
+       FILE *f = popen(commandline, "r");
        if (f == NULL) {
                fprintf(stderr, "invoking preprocessor failed\n");
                exit(EXIT_FAILURE);
        }
-
        /* we don't really need that anymore */
-       obstack_free(&cppflags_obst, buf);
+       obstack_free(&cppflags_obst, commandline);
 
        return f;
 }
 
 static void assemble(const char *out, const char *in)
 {
-       struct obstack asflags_obst;
-       char *buf;
-
-       obstack_init(&asflags_obst);
+       obstack_1grow(&asflags_obst, '\0');
+       const char *flags = obstack_finish(&asflags_obst);
 
        const char *assembler = getenv("CPARSER_AS");
        if (assembler != NULL) {
-               obstack_printf(&asflags_obst, "%s ", assembler);
+               obstack_printf(&asflags_obst, "%s", assembler);
        } else {
                if (target_triple != NULL)
                        obstack_printf(&asflags_obst, "%s-", target_triple);
-               obstack_printf(&asflags_obst, "%s ", ASSEMBLER);
+               obstack_printf(&asflags_obst, "%s", ASSEMBLER);
        }
+       if (flags[0] != '\0')
+               obstack_printf(&asflags_obst, " %s", flags);
 
-       obstack_printf(&asflags_obst, "%s -o %s", in, out);
+       obstack_printf(&asflags_obst, " %s -o %s", in, out);
        obstack_1grow(&asflags_obst, '\0');
-       buf = obstack_finish(&asflags_obst);
 
+       char *commandline = obstack_finish(&asflags_obst);
        if (verbose) {
-               puts(buf);
+               puts(commandline);
        }
-
-       int err = system(buf);
-       if (err != 0) {
+       int err = system(commandline);
+       if (err != EXIT_SUCCESS) {
                fprintf(stderr, "assembler reported an error\n");
                exit(EXIT_FAILURE);
        }
-
-       obstack_free(&asflags_obst, NULL);
+       obstack_free(&asflags_obst, commandline);
 }
 
 static void print_file_name(const char *file)
@@ -408,7 +403,6 @@ static void print_file_name(const char *file)
        obstack_1grow(&ldflags_obst, '\0');
 
        char *commandline = obstack_finish(&ldflags_obst);
-
        if (verbose) {
                puts(commandline);
        }
@@ -417,6 +411,7 @@ static void print_file_name(const char *file)
                fprintf(stderr, "linker reported an error\n");
                exit(EXIT_FAILURE);
        }
+       obstack_free(&ldflags_obst, commandline);
 }
 
 static const char *try_dir(const char *dir)
@@ -531,7 +526,6 @@ typedef enum compile_mode_t {
        LexTest,
        PrintAst,
        PrintFluffy,
-       PrintCaml,
        PrintJna
 } compile_mode_t;
 
@@ -578,13 +572,6 @@ static void set_be_option(const char *arg)
        assert(res);
 }
 
-static void set_option(const char *arg)
-{
-       int res = firm_option(arg);
-       (void) res;
-       assert(res);
-}
-
 static void copy_file(FILE *dest, FILE *input)
 {
        char buf[16384];
@@ -597,20 +584,6 @@ static void copy_file(FILE *dest, FILE *input)
        }
 }
 
-static inline bool streq(char const* a, char const* b)
-{
-       return strcmp(a, b) == 0;
-}
-
-static inline bool strstart(char const* str, char const* start)
-{
-       do {
-               if (*start == '\0')
-                       return true;
-       } while (*str++ == *start++);
-       return false;
-}
-
 static FILE *open_file(const char *filename)
 {
        if (streq(filename, "-")) {
@@ -643,29 +616,22 @@ static filetype_t get_filetype_from_string(const char *string)
        return FILETYPE_UNKNOWN;
 }
 
-/**
- * Initialize firm codegeneration for a specific operating system.
- * The argument is the operating system part of a target-triple */
-static bool set_os_support(const char *os)
+static bool init_os_support(void)
 {
+       const char *os = target_machine->operating_system;
        wchar_atomic_kind         = ATOMIC_TYPE_INT;
        force_long_double_size    = 0;
        enable_main_collect2_hack = false;
 
        if (strstr(os, "linux") != NULL || strstr(os, "bsd") != NULL
                        || streq(os, "solaris")) {
-               set_be_option("ia32-gasmode=elf");
                set_create_ld_ident(create_name_linux_elf);
        } else if (streq(os, "darwin")) {
                force_long_double_size = 16;
-               set_be_option("ia32-gasmode=macho");
-               set_be_option("ia32-stackalign=4");
-               set_be_option("pic=true");
                set_create_ld_ident(create_name_macho);
        } else if (strstr(os, "mingw") != NULL || streq(os, "win32")) {
                wchar_atomic_kind         = ATOMIC_TYPE_USHORT;
                enable_main_collect2_hack = true;
-               set_be_option("ia32-gasmode=mingw");
                set_create_ld_ident(create_name_win32);
        } else {
                return false;
@@ -676,65 +642,11 @@ static bool set_os_support(const char *os)
 
 static bool parse_target_triple(const char *arg)
 {
-       const char *manufacturer = strchr(arg, '-');
-       if (manufacturer == NULL) {
+       machine_triple_t *triple = firm_parse_machine_triple(arg);
+       if (triple == NULL) {
                fprintf(stderr, "Target-triple is not in the form 'cpu_type-manufacturer-operating_system'\n");
                return false;
        }
-       manufacturer += 1;
-
-       const char *os = strchr(manufacturer, '-');
-       if (os == NULL) {
-               fprintf(stderr, "Target-triple is not in the form 'cpu_type-manufacturer-operating_system'\n");
-               return false;
-       }
-       os += 1;
-
-       /* Note: Triples are more or less defined by what the config.guess and
-        * config.sub scripts from GNU autoconf emit. We have to lookup there what
-        * triples are possible */
-
-       /* process cpu type */
-       if (strstart(arg, "i386-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i386");
-       } else if (strstart(arg, "i486-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i486");
-       } else if (strstart(arg, "i586-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i586");
-       } else if (strstart(arg, "i686-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i686");
-       } else if (strstart(arg, "i786-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=pentium4");
-       } else if (strstart(arg, "x86_64")) {
-               be_parse_arg("isa=amd64");
-       } else if (strstart(arg, "sparc-")) {
-               be_parse_arg("isa=sparc");
-       } else if (strstart(arg, "arm-")) {
-               be_parse_arg("isa=arm");
-       } else {
-               fprintf(stderr, "Unknown cpu in triple '%s'\n", arg);
-               return false;
-       }
-
-       /* process manufacturer, alot of people incorrectly leave out the
-        * manufacturer instead of using unknown- */
-       if (strstart(manufacturer, "linux")) {
-               os = manufacturer;
-               manufacturer = "unknown-";
-       }
-
-       /* process operating system */
-       if (!set_os_support(os)) {
-               fprintf(stderr, "Unknown operating system '%s' in triple '%s'\n", os, arg);
-               return false;
-       }
-
-       target_triple = arg;
        return true;
 }
 
@@ -764,6 +676,7 @@ int main(int argc, char **argv)
 
        obstack_init(&cppflags_obst);
        obstack_init(&ldflags_obst);
+       obstack_init(&asflags_obst);
        obstack_init(&file_obst);
 
 #define GET_ARG_AFTER(def, args)                                             \
@@ -797,42 +710,15 @@ int main(int argc, char **argv)
                }
        }
 
-       /* Guess host OS */
-#if defined(_WIN32) || defined(__CYGWIN__)
-       set_os_support("win32");
-#elif defined(__APPLE__)
-       set_os_support("darwin");
-#else
-       set_os_support("linux");
-#endif
-
-       /* apply optimisation level */
-       switch(opt_level) {
-       case 0:
-               set_option("no-opt");
-               break;
-       case 1:
-               set_option("no-inline");
-               break;
-       default:
-       case 4:
-               /* use_builtins = true; */
-               /* fallthrough */
-       case 3:
-               set_option("thread-jumps");
-               set_option("if-conversion");
-               /* fallthrough */
-       case 2:
-               set_option("strict-aliasing");
-               set_option("inline");
-               set_option("deconv");
-               set_be_option("omitfp");
-               break;
-       }
-
        const char *target = getenv("TARGET");
        if (target != NULL)
                parse_target_triple(target);
+       if (target_machine == NULL) {
+               target_machine = firm_get_host_machine();
+       }
+       choose_optimization_pack(opt_level);
+       setup_firm_for_machine(target_machine);
+       init_os_support();
 
        /* parse rest of options */
        standard                   = STANDARD_DEFAULT;
@@ -1046,12 +932,20 @@ int main(int argc, char **argv)
                                GET_ARG_AFTER(opt, "-m");
                                if (strstart(opt, "target=")) {
                                        GET_ARG_AFTER(opt, "-mtarget=");
-                                       if (!parse_target_triple(opt))
+                                       if (!parse_target_triple(opt)) {
                                                argument_errors = true;
+                                       } else {
+                                               setup_firm_for_machine(target_machine);
+                                               target_triple = opt;
+                                       }
                                } else if (strstart(opt, "triple=")) {
                                        GET_ARG_AFTER(opt, "-mtriple=");
-                                       if (!parse_target_triple(opt))
+                                       if (!parse_target_triple(opt)) {
                                                argument_errors = true;
+                                       } else {
+                                               setup_firm_for_machine(target_machine);
+                                               target_triple = opt;
+                                       }
                                } else if (strstart(opt, "arch=")) {
                                        GET_ARG_AFTER(opt, "-march=");
                                        snprintf(arch_opt, sizeof(arch_opt), "%s-arch=%s", cpu_arch, opt);
@@ -1121,6 +1015,8 @@ int main(int argc, char **argv)
                                                argument_errors = true;
                                        } else {
                                                machine_size = (unsigned int)value;
+                                               add_flag(&asflags_obst, "-m%u", machine_size);
+                                               add_flag(&ldflags_obst, "-m%u", machine_size);
                                        }
                                }
                        } else if (streq(option, "pg")) {
@@ -1181,8 +1077,6 @@ int main(int argc, char **argv)
                                        print_parenthesis = true;
                                } else if (streq(option, "print-fluffy")) {
                                        mode = PrintFluffy;
-                               } else if (streq(option, "print-caml")) {
-                                       mode = PrintCaml;
                                } else if (streq(option, "print-jna")) {
                                        mode = PrintJna;
                                } else if (streq(option, "jna-limit")) {
@@ -1297,9 +1191,6 @@ int main(int argc, char **argv)
                return EXIT_FAILURE;
        }
 
-       /* we do the lowering in ast2firm */
-       firm_opt.lower_bitfields = FALSE;
-
        /* set the c_mode here, types depends on it */
        c_mode |= features_on;
        c_mode &= ~features_off;
@@ -1337,7 +1228,6 @@ int main(int argc, char **argv)
                case BenchmarkParser:
                case PrintAst:
                case PrintFluffy:
-               case PrintCaml:
                case PrintJna:
                case LexTest:
                case PreprocessOnly:
@@ -1537,9 +1427,6 @@ do_parsing:
                        } else if (mode == PrintFluffy) {
                                write_fluffy_decls(out, unit);
                                continue;
-                       } else if (mode == PrintCaml) {
-                               write_caml_decls(out, unit);
-                               continue;
                        } else if (mode == PrintJna) {
                                write_jna_decls(out, unit);
                                continue;
@@ -1592,7 +1479,7 @@ graph_built:
                                return EXIT_SUCCESS;
                        }
 
-                       gen_firm_finish(asm_out, filename, have_const_functions);
+                       gen_firm_finish(asm_out, filename);
                        if (asm_out != out) {
                                fclose(asm_out);
                        }
@@ -1699,6 +1586,7 @@ graph_built:
 
        obstack_free(&cppflags_obst, NULL);
        obstack_free(&ldflags_obst, NULL);
+       obstack_free(&asflags_obst, NULL);
        obstack_free(&file_obst, NULL);
 
        exit_mangle();