Example #1
0
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");
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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);
	}
}
Example #5
0
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;
}