option was parsed twice
[cparser] / main.c
diff --git a/main.c b/main.c
index 702ef70..462258e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -72,7 +72,9 @@
 #include "driver/firm_opt.h"
 #include "driver/firm_cmdline.h"
 #include "driver/firm_timing.h"
+#include "driver/firm_machine.h"
 #include "adt/error.h"
+#include "adt/strutil.h"
 #include "wrappergen/write_fluffy.h"
 #include "wrappergen/write_jna.h"
 #include "revision.h"
 #endif
 
 #ifndef ASSEMBLER
-#ifdef __APPLE__
 #define ASSEMBLER "gcc -c -xassembler"
-#else
-#define ASSEMBLER "as"
-#endif
 #endif
 
 unsigned int       c_mode                    = _C89 | _ANSI | _C99 | _GNUC;
@@ -117,13 +115,15 @@ 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;
-static struct obstack  ldflags_obst;
-static struct obstack  asflags_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;
+static bool              define_intmax_types;
 
 typedef enum lang_standard_t {
        STANDARD_DEFAULT, /* gnu99 (for C, GCC does gnu89) or gnu++98 (for C++) */
@@ -162,11 +162,6 @@ struct file_list_entry_t {
 
 static file_list_entry_t *temp_files;
 
-static void initialize_firm(void)
-{
-       firm_early_init();
-}
-
 static void get_output_name(char *buf, size_t buflen, const char *inputname,
                             const char *newext)
 {
@@ -289,6 +284,13 @@ static FILE *preprocess(const char *fname, filetype_t filetype)
                add_flag(&cppflags_obst, "-U__VERSION__");
                add_flag(&cppflags_obst, "-D__VERSION__=\"%s\"", cparser_REVISION);
 
+               if (define_intmax_types) {
+                       add_flag(&cppflags_obst, "-U__INTMAX_TYPE__");
+                       add_flag(&cppflags_obst, "-D__INTMAX_TYPE__=%s", type_to_string(type_intmax_t));
+                       add_flag(&cppflags_obst, "-U__UINTMAX_TYPE__");
+                       add_flag(&cppflags_obst, "-D__UINTMAX_TYPE__=%s", type_to_string(type_uintmax_t));
+               }
+
                if (flags[0] != '\0') {
                        size_t len = strlen(flags);
                        obstack_1grow(&cppflags_obst, ' ');
@@ -573,13 +575,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];
@@ -592,20 +587,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, "-")) {
@@ -638,29 +619,24 @@ 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;
+       define_intmax_types       = 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);
+               define_intmax_types = true;
        } 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;
@@ -671,71 +647,25 @@ static bool set_os_support(const char *os)
 
 static bool parse_target_triple(const char *arg)
 {
-       const char *manufacturer = strchr(arg, '-');
-       if (manufacturer == 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) {
+       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;
        }
-       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;
+       target_machine = triple;
        return true;
 }
 
+static void setup_target_machine(void)
+{
+       if (!setup_firm_for_machine(target_machine))
+               exit(1);
+       init_os_support();
+}
+
 int main(int argc, char **argv)
 {
-       initialize_firm();
+       firm_early_init();
 
        const char        *dumpfunction         = NULL;
        const char        *print_file_name_file = NULL;
@@ -747,6 +677,8 @@ int main(int argc, char **argv)
        file_list_entry_t *last_file            = NULL;
        bool               construct_dep_target = false;
        bool               do_timing            = false;
+       bool               profile_generate     = false;
+       bool               profile_use          = false;
        struct obstack     file_obst;
 
        atexit(free_temp_files);
@@ -793,43 +725,14 @@ 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("fp-vrp");
-               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_target_machine();
 
        /* parse rest of options */
        standard                   = STANDARD_DEFAULT;
@@ -940,9 +843,14 @@ int main(int argc, char **argv)
                                if (strstart(orig_opt, "input-charset=")) {
                                        char const* const encoding = strchr(orig_opt, '=') + 1;
                                        select_input_encoding(encoding);
-                               } else if (streq(orig_opt, "verbose-asm")) {
-                                       /* ignore: we always print verbose assembler */
+                               } else if (strstart(orig_opt, "align-loops=") ||
+                                          strstart(orig_opt, "align-jumps=") ||
+                                          strstart(orig_opt, "align-functions=")) {
+                                       fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
+                               } else if (strstart(orig_opt, "message-length=")) {
+                                       /* ignore: would only affect error message format */
                                } else {
+                                       /* -f options which have an -fno- variant */
                                        char const *opt         = orig_opt;
                                        bool        truth_value = true;
                                        if (opt[0] == 'n' && opt[1] == 'o' && opt[2] == '-') {
@@ -968,19 +876,19 @@ int main(int argc, char **argv)
                                        } else if (streq(opt, "unsigned-char")) {
                                                char_is_signed = !truth_value;
                                        } else if (streq(opt, "freestanding")) {
-                                               freestanding = true;
+                                               freestanding = truth_value;
                                        } else if (streq(opt, "hosted")) {
-                                               freestanding = false;
-                                       } else if (truth_value == false &&
+                                               freestanding = !truth_value;
+                                       } else if (streq(opt, "profile-generate")) {
+                                               profile_generate = truth_value;
+                                       } else if (streq(opt, "profile-use")) {
+                                               profile_use = truth_value;
+                                       } else if (!truth_value &&
                                                   streq(opt, "asynchronous-unwind-tables")) {
                                            /* nothing todo, a gcc feature which we don't support
                                             * anyway was deactivated */
-                                       } else if (strstart(orig_opt, "align-loops=") ||
-                                                       strstart(orig_opt, "align-jumps=") ||
-                                                       strstart(orig_opt, "align-functions=")) {
-                                               fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
-                                       } else if (strstart(orig_opt, "message-length=")) {
-                                                       /* ignore: would only affect error message format */
+                                       } else if (streq(orig_opt, "verbose-asm")) {
+                                               /* ignore: we always print verbose assembler */
                                        } else if (streq(opt, "fast-math")               ||
                                                   streq(opt, "jump-tables")             ||
                                                   streq(opt, "expensive-optimizations") ||
@@ -1043,12 +951,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_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_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);
@@ -1118,7 +1034,7 @@ int main(int argc, char **argv)
                                                argument_errors = true;
                                        } else {
                                                machine_size = (unsigned int)value;
-                                               add_flag(&asflags_obst, "--%u", machine_size);
+                                               add_flag(&asflags_obst, "-m%u", machine_size);
                                                add_flag(&ldflags_obst, "-m%u", machine_size);
                                        }
                                }
@@ -1128,8 +1044,6 @@ int main(int argc, char **argv)
                        } else if (streq(option, "pedantic") ||
                                   streq(option, "ansi")) {
                                fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg);
-                       } else if (streq(option, "shared")) {
-                               add_flag(&ldflags_obst, "-shared");
                        } else if (strstart(option, "std=")) {
                                const char *const o = &option[4];
                                standard =
@@ -1243,6 +1157,7 @@ int main(int argc, char **argv)
                                                        streq(suffix, "S")   ? FILETYPE_ASSEMBLER              :
                                                        streq(suffix, "a")   ? FILETYPE_OBJECT                 :
                                                        streq(suffix, "c")   ? FILETYPE_C                      :
+                                                       streq(suffix, "i")   ? FILETYPE_PREPROCESSED_C         :
                                                        streq(suffix, "C")   ? FILETYPE_CXX                    :
                                                        streq(suffix, "cc")  ? FILETYPE_CXX                    :
                                                        streq(suffix, "cp")  ? FILETYPE_CXX                    :
@@ -1250,7 +1165,7 @@ int main(int argc, char **argv)
                                                        streq(suffix, "CPP") ? FILETYPE_CXX                    :
                                                        streq(suffix, "cxx") ? FILETYPE_CXX                    :
                                                        streq(suffix, "c++") ? FILETYPE_CXX                    :
-                                                       streq(suffix, "ii")  ? FILETYPE_CXX                    :
+                                                       streq(suffix, "ii")  ? FILETYPE_PREPROCESSED_CXX       :
                                                        streq(suffix, "h")   ? FILETYPE_C                      :
                                                        streq(suffix, "ir")  ? FILETYPE_IR                     :
                                                        streq(suffix, "o")   ? FILETYPE_OBJECT                 :
@@ -1294,9 +1209,16 @@ int main(int argc, char **argv)
                return EXIT_FAILURE;
        }
 
-       /* set the c_mode here, types depends on it */
+       /* apply some effects from switches */
        c_mode |= features_on;
        c_mode &= ~features_off;
+       if (profile_generate) {
+               add_flag(&ldflags_obst, "-lfirmprof");
+               set_be_option("profilegenerate");
+       }
+       if (profile_use) {
+               set_be_option("profileuse");
+       }
 
        gen_firm_init();
        byte_order_big_endian = be_get_backend_param()->byte_order_big_endian;