static void init_generic_elf(void) { driver_default_exe_output = "a.out"; set_create_ld_ident(create_name_elf); target.object_format = OBJECT_FORMAT_ELF; set_be_option("ia32-struct_in_reg=no"); }
bool options_parse_linker(options_state_t *s) { const char *full_option = s->argv[s->i]; if (full_option[0] != '-') return false; const char *arg; if ((arg = prefix_arg("l", s)) != NULL) { driver_add_flag(&ldflags_obst, "-l%s", arg); } else if ((arg = prefix_arg("L", s)) != NULL) { driver_add_flag(&ldflags_obst, "-L%s", arg); } else if (simple_arg("static", s) || simple_arg("no-pie", s) || simple_arg("nodefaultlibs", s) || simple_arg("nostartfiles", s) || simple_arg("nostdlib", s) || simple_arg("pie", s) || simple_arg("rdynamic", s) || simple_arg("s", s) || simple_arg("shared", s) || simple_arg("shared-libgcc", s) || simple_arg("static-libgcc", s) || simple_arg("symbolic", s) || accept_prefix(s, "-Wl,", true, &arg)) { driver_add_flag(&ldflags_obst, full_option); } else if ((arg = spaced_arg("Xlinker", s)) != NULL) { driver_add_flag(&ldflags_obst, "-Xlinker"); driver_add_flag(&ldflags_obst, arg); } else if (simple_arg("pg", s)) { set_be_option("gprof"); driver_add_flag(&ldflags_obst, "-pg"); } else if ((arg = equals_arg("print-file-name", s)) != NULL) { print_file_name_file = arg; s->action = action_print_file_name; } else { return false; } return true; }
static bool pass_options_to_firm_be(void) { switch (target.object_format) { case OBJECT_FORMAT_ELF: set_be_option("objectformat=elf"); break; case OBJECT_FORMAT_MACH_O: set_be_option("objectformat=mach-o"); break; case OBJECT_FORMAT_PE_COFF: set_be_option("objectformat=coff"); break; } if (profile_generate) { driver_add_flag(&ldflags_obst, "-lfirmprof"); set_be_option("profilegenerate"); } if (profile_use) { set_be_option("profileuse"); } bool res = true; const char *pic_option; if (target.pic_mode > 0) { /* Select correct PIC mode */ if (target.object_format == OBJECT_FORMAT_MACH_O) { pic_option = "pic=mach-o"; } else { pic_option = target.pic_no_plt ? "pic=elf-noplt" : "pic=elf"; } } else { pic_option = "pic=none"; } set_be_option(pic_option); /* pass options to firm backend (this happens delayed because we first * had to decide which backend is actually used) */ for (codegen_option_t *option = codegen_options; option != NULL; option = option->next) { char buf[256]; const char *opt = option->option; /* pass option along to firm backend (except the -m32, -m64 stuff) */ snprintf(buf, sizeof(buf), "%s-%s", target.firm_isa, opt); if (be_parse_arg(buf) == 0) { errorf(NULL, "Unknown codegen option '-m%s'", opt); res = false; continue; } /* hack to emulate the behaviour of some gcc spec files which filter * flags to pass to cpp/ld/as */ static char const *const pass_to_cpp_and_ld[] = { "soft-float" }; for (size_t i = 0; i < ARRAY_SIZE(pass_to_cpp_and_ld); ++i) { if (streq(pass_to_cpp_and_ld[i], option->option)) { snprintf(buf, sizeof(buf), "-m%s", option->option); driver_add_flag(&cppflags_obst, buf); driver_add_flag(&asflags_obst, buf); driver_add_flag(&ldflags_obst, buf); break; } } } /* We can initialize the backend at this point and call be_get_backend_param() */ if (target.pic_mode > 0 && !be_get_backend_param()->pic_supported) { errorf(NULL, "Selected backend '%s' does not support position independent code (PIC)", target.firm_isa); res = false; } return res; }
static void set_options_for_machine(machine_triple_t const *const machine) { /* Note: Code here should only check the target triple! Querying other * target features is not allowed as subsequent commandline options may * change those. Example: * ppdefc("X", "Y", cond_not_strict); // Correct: cond_not_strict is * // evaluated later * if (dialect.gnu) * ppdef("X", "Y"); // Wrong: language dialect/target is not final yet */ const char *const cpu = machine->cpu_type; const char *const manufacturer = machine->manufacturer; const char *const os = machine->operating_system; unsigned pointer_size; unsigned long_double_size; unsigned modulo_shift; float_int_conversion_overflow_style_t float_int_overflow; const char *firm_isa; if (target.firm_isa_specified) { /* Firm ISA was specified on the commandline, this may be used to * experiment with new firm backends. */ firm_isa = target.firm_isa; unsigned size = target_size_override != 0 ? target_size_override/BITS_PER_BYTE : 4; pointer_size = size; long_double_size = 8; modulo_shift = size * BITS_PER_BYTE; float_int_overflow = ir_overflow_indefinite; /* i386, i486, i586, i686, i786 */ } else if (is_ia32_cpu(cpu)) { ppdefc("i386", "1", cond_not_strict); ppdef( "__i386", "1"); ppdef( "__i386__", "1"); switch (cpu[1]) { case '4': ppdef("__i486", "1"); ppdef("__i486__", "1"); break; case '5': ppdef("__i586", "1"); ppdef("__i586__", "1"); ppdef("__pentium", "1"); ppdef("__pentium__", "1"); //ppdef("__pentium_mmx__", "1"); break; case '6': ppdef("__pentiumpro", "1"); ppdef("__pentiumpro__", "1"); ppdef("__i686", "1"); ppdef("__i686__", "1"); break; case '7': ppdef("__pentium4", "1"); ppdef("__pentium4__", "1"); break; } firm_isa = "ia32"; pointer_size = 4; modulo_shift = 32; long_double_size = 12; float_int_overflow = ir_overflow_indefinite; target.firm_arch = cpu; /* long long and double has a 4 byte alignment inside structs, this odd * mode is everywhere except for windows OSes (they will revert it * below) */ dialect.long_long_and_double_struct_align = 4; dialect.long_double_x87_80bit_float = true; } else if (streq(cpu, "sparc")) { ppdefc("sparc", "1", cond_not_strict); ppdef( "__sparc", "1"); ppdef( "__sparc__", "1"); /* we always produce sparc V8 code at the moment */ ppdef( "__sparc_v8__", "1"); if (strstr(manufacturer, "leon") != NULL || streq(manufacturer, "invasic")) { ppdef("__leon__", "1"); set_be_option("sparc-cpu=leon"); } firm_isa = "sparc"; pointer_size = 4; modulo_shift = 32; long_double_size = 16; float_int_overflow = ir_overflow_min_max; target.byte_order_big_endian = true; } else if (streq(cpu, "arm")) { /* TODO: test, what about * ARM_FEATURE_UNALIGNED, ARMEL, ARM_ARCH_7A, ARM_FEATURE_DSP, ... */ ppdef("__arm__", "1"); if (strstr(os, "eabi") != NULL) ppdef("__ARM_EABI__", "1"); firm_isa = "arm"; pointer_size = 4; modulo_shift = 256; long_double_size = 8; float_int_overflow = ir_overflow_min_max; } else if (is_amd64_cpu(cpu)) { ppdef("__x86_64", "1"); ppdef("__x86_64__", "1"); ppdef("__amd64", "1"); ppdef("__amd64__", "1"); firm_isa = "amd64"; pointer_size = 8; modulo_shift = 32; long_double_size = 16; float_int_overflow = ir_overflow_indefinite; dialect.long_double_x87_80bit_float = true; } else { errorf(NULL, "unknown cpu '%s' in target-triple", cpu); exit(EXIT_FAILURE); } target.firm_isa = firm_isa; target.modulo_shift = modulo_shift; target.float_int_overflow = float_int_overflow; dialect.pointer_size = pointer_size; dialect.int_size = MIN(pointer_size, 4); dialect.long_size = MIN(pointer_size, 8); dialect.long_double_size = long_double_size; dialect.wchar_atomic_kind = ATOMIC_TYPE_INT; dialect.pointer_sized_int = ATOMIC_TYPE_LONG; dialect.pointer_sized_uint = ATOMIC_TYPE_ULONG; set_compilerlib_name_mangle(compilerlib_name_mangle); if (strstr(os, "linux") != NULL) { init_generic_elf(); init_unix(); ppdef( "__linux", "1"); ppdef( "__linux__", "1"); ppdefc("linux", "1", cond_not_strict); if (strstr(os, "gnu") != NULL) ppdef("__gnu_linux__", "1"); } else if (strstr(os, "bsd") != NULL) { init_generic_elf(); init_unix(); } else if (streq(os, "elf") || streq(os, "octopos") || streq(os, "irtss")) { init_generic_elf(); } else if (strstart(os, "darwin")) { driver_default_exe_output = "a.out"; set_create_ld_ident(create_name_macho); target.user_label_prefix = "_"; target.object_format = OBJECT_FORMAT_MACH_O; target.pic_mode = 2; set_be_option("ia32-stackalign=4"); set_be_option("ia32-struct_in_reg=yes"); dialect.long_double_size = 16; ppdef( "__MACH__", "1"); ppdef( "__APPLE__", "1"); ppdef( "__APPLE_CC__", "1"); ppdef( "__weak", ""); ppdef( "__strong", ""); ppdef( "__CONSTANT_CFSTRINGS__", "1"); ppdef( "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", "1050"); ppdef( "__DYNAMIC__", "1"); ppdefc("__LITTLE_ENDIAN__", "1", cond_is_little_endian); } else if (strstart(os, "mingw")) { dialect.wchar_atomic_kind = ATOMIC_TYPE_USHORT; driver_default_exe_output = "a.exe"; target.object_format = OBJECT_FORMAT_PE_COFF; set_be_option("ia32-struct_in_reg=no"); dialect.enable_main_collect2_hack = true; ppdef("__MINGW32__", "1"); dialect.long_long_and_double_struct_align = 0; ppdef( "__MSVCRT__", "1"); ppdef( "_WINNT", "1"); ppdef( "__WINNT", "1"); ppdef( "__WINNT__", "1"); ppdefc("WINNT", "1", cond_not_strict); ppdef( "_WIN32", "1"); ppdef( "__WIN32", "1"); ppdef( "__WIN32__", "1"); ppdefc("WIN32", "1", cond_not_strict); if (pointer_size == 8) { set_be_option("amd64-x64abi=yes"); set_create_ld_ident(create_name_win64); ppdef( "_WIN64", "1"); ppdef( "__WIN64", "1"); ppdef( "__WIN64__", "1"); ppdefc("WIN64", "1", cond_not_strict); ppdef( "__MINGW64__", "1"); /* to ease porting of old c-code microsoft decided to use 32bits * even for long */ dialect.long_size = 4; dialect.pointer_sized_int = ATOMIC_TYPE_LONGLONG; dialect.pointer_sized_uint = ATOMIC_TYPE_ULONGLONG; } else { assert(pointer_size == 4); set_create_ld_ident(create_name_win32); target.user_label_prefix = "_"; dialect.pointer_sized_int = ATOMIC_TYPE_INT; dialect.pointer_sized_uint = ATOMIC_TYPE_UINT; } } else if (strstart(os, "midipix")) { driver_default_exe_output = "a.out"; target.object_format = OBJECT_FORMAT_PE_COFF; set_be_option("ia32-struct_in_reg=no"); dialect.long_long_and_double_struct_align = 0; ppdef("__midipix__", "1"); if (pointer_size == 8) { set_be_option("amd64-x64abi=yes"); set_create_ld_ident(create_name_win64); ppdef("__NT64", "1"); } else { assert(pointer_size == 4); set_create_ld_ident(create_name_win32); target.user_label_prefix = "_"; ppdef("__NT32", "1"); } } else { errorf(NULL, "unknown operating system '%s' in target-triple", os); exit(EXIT_FAILURE); } }
bool options_parse_codegen(options_state_t *s) { const char *full_option = s->argv[s->i]; if (full_option[0] != '-') return false; const char *option = &full_option[1]; const char *arg; if ((arg = equals_arg("falign-loops", s)) != NULL || (arg = equals_arg("falign-jumps", s)) != NULL || (arg = equals_arg("falign-functions", s)) != NULL) { warningf(WARN_COMPAT_OPTION, NULL, "ignoring gcc option '%s'", full_option); } else if ((arg = equals_arg("fvisibility", s)) != NULL) { elf_visibility_t visibility = get_elf_visibility_from_string(arg); if (visibility == ELF_VISIBILITY_ERROR) { errorf(NULL, "invalid visibility '%s' specified", arg); s->argument_errors = true; } else { set_default_visibility(visibility); } } else if (accept_prefix(s, "-b", true, &arg)) { if (!be_parse_arg(arg)) { errorf(NULL, "invalid backend option '%s' (unknown option or invalid argument)", full_option); s->argument_errors = true; } else if ((arg = equals_arg("bisa", s)) != NULL) { /* This is a quick and dirty option to try out new firm targets. * Sooner rather than later the new target should be added properly * to target.c! */ target.firm_isa_specified = true; target.firm_isa = arg; } } else if (simple_arg("-unroll-loops", s)) { /* ignore (gcc compatibility) */ } else if (simple_arg("fexcess-precision=standard", s)) { /* ignore (gcc compatibility) we always adhere to the C99 standard * anyway in this respect */ } else if (accept_prefix(s, "-g", false, &arg)) { if (streq(arg, "0")) { set_be_option("debug=none"); set_be_option("ia32-optcc=true"); } else { set_be_option("debug=frameinfo"); set_be_option("ia32-optcc=false"); } } else if (accept_prefix(s, "-m", false, &arg)) { arg = &option[1]; /* remember option for backend */ assert(obstack_object_size(&codegenflags_obst) == 0); obstack_blank(&codegenflags_obst, sizeof(codegen_option_t)); size_t len = strlen(arg); obstack_grow(&codegenflags_obst, arg, len); codegen_option_t *const cg_option = obstack_nul_finish(&codegenflags_obst); cg_option->next = NULL; *codegen_options_anchor = cg_option; codegen_options_anchor = &cg_option->next; } else { bool truth_value; const char *fopt; if ((fopt = f_no_arg(&truth_value, s)) != NULL) { if (f_yesno_arg("-ffast-math", s)) { ir_allow_imprecise_float_transforms(truth_value); } else if (f_yesno_arg("-fomit-frame-pointer", s)) { set_be_option(truth_value ? "omitfp" : "omitfp=no"); } else if (f_yesno_arg("-fstrength-reduce", s)) { /* does nothing, for gcc compatibility (even gcc does * nothing for this switch anymore) */ } else if (!truth_value && (f_yesno_arg("-fasynchronous-unwind-tables", s) || f_yesno_arg("-funwind-tables", s))) { /* do nothing: a gcc feature which we do not support * anyway was deactivated */ } else if (f_yesno_arg("-frounding-math", s)) { /* ignore for gcc compatibility: we don't have any unsafe * optimizations in that area */ } else if (f_yesno_arg("-fverbose-asm", s)) { set_be_option(truth_value ? "verboseasm" : "verboseasm=no"); } else if (f_yesno_arg("-fPIC", s)) { target.pic_mode = truth_value ? 2 : 0; } else if (f_yesno_arg("-fpic", s)) { target.pic_mode = truth_value ? 1 : 0; } else if (f_yesno_arg("-fplt", s)) { target.pic_no_plt = !truth_value; } else if (f_yesno_arg("-fjump-tables", s) || f_yesno_arg("-fexpensive-optimizations", s) || f_yesno_arg("-fcommon", s) || f_yesno_arg("-foptimize-sibling-calls", s) || f_yesno_arg("-falign-loops", s) || f_yesno_arg("-falign-jumps", s) || f_yesno_arg("-falign-functions", s) || f_yesno_arg("-fstack-protector", s) || f_yesno_arg("-fstack-protector-all", s)) { /* better warn the user for these as he might have expected * that something happens */ warningf(WARN_COMPAT_OPTION, NULL, "ignoring gcc option '-f%s'", fopt); } else if (firm_option(&option[1])) { /* parsed a firm option */ } else { return false; } } else { return false; } } return true; }