diff options
author | Matthias Braun <matze@braunis.de> | 2017-01-01 18:48:49 +0100 |
---|---|---|
committer | Matthias Braun <matze@braunis.de> | 2017-02-20 04:48:33 +0100 |
commit | 1e671622e9015458d90974b4ed8a14fecb166bc1 (patch) | |
tree | 986b0abe992d111ca9ef5b5eedac029611d594a8 | |
parent | d35d57ebf0d828a43e700358f0a011a27ce1c31b (diff) |
Use new libfirm target API
This moves the target and platform knowledge and initialization into
libfirm.
m--------- | libfirm | 0 | ||||
-rw-r--r-- | src/ast/ast.c | 6 | ||||
-rw-r--r-- | src/ast/constfold.c | 79 | ||||
-rw-r--r-- | src/ast/dialect.h | 39 | ||||
-rw-r--r-- | src/ast/type.c | 27 | ||||
-rw-r--r-- | src/ast/type.h | 6 | ||||
-rw-r--r-- | src/ast/types.c | 30 | ||||
-rw-r--r-- | src/driver/actions.c | 11 | ||||
-rw-r--r-- | src/driver/c_driver.c | 6 | ||||
-rw-r--r-- | src/driver/c_driver.h | 5 | ||||
-rw-r--r-- | src/driver/help.c | 11 | ||||
-rw-r--r-- | src/driver/machine_triple.c | 60 | ||||
-rw-r--r-- | src/driver/machine_triple.h | 20 | ||||
-rw-r--r-- | src/driver/options.c | 53 | ||||
-rw-r--r-- | src/driver/predefs.c | 24 | ||||
-rw-r--r-- | src/driver/target.c | 606 | ||||
-rw-r--r-- | src/driver/target.h | 59 | ||||
-rw-r--r-- | src/firm/ast2firm.c | 16 | ||||
-rw-r--r-- | src/firm/firm_opt.c | 21 | ||||
-rw-r--r-- | src/firm/firm_opt.h | 2 | ||||
-rw-r--r-- | src/main.c | 6 |
21 files changed, 291 insertions, 796 deletions
diff --git a/libfirm b/libfirm -Subproject 78a5cf6805cf3f85005926b177f48c33adcdddd +Subproject 1ffc842f8bb13ed098eeaf2382ba473f9e15446 diff --git a/src/ast/ast.c b/src/ast/ast.c index cad65fd..85bb39f 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -37,12 +37,8 @@ #include "type_t.h" #include "types.h" -c_dialect_t dialect = { - .char_is_signed = true, - .long_long_size = 8, -}; - struct obstack ast_obstack; +c_dialect_t dialect; static int indent; static int case_indent; diff --git a/src/ast/constfold.c b/src/ast/constfold.c index ba856a2..d9f072e 100644 --- a/src/ast/constfold.c +++ b/src/ast/constfold.c @@ -993,13 +993,6 @@ bool fold_expression_to_bool(const expression_t *expression) } } -static unsigned decide_modulo_shift(unsigned type_size) -{ - if (target.modulo_shift == 0) - return 0; - return MAX(type_size, target.modulo_shift); -} - bool enum_bitfield_big_enough(enum_t *enume, type_t *base_type, unsigned bitfield_size) { @@ -1038,57 +1031,33 @@ bool enum_bitfield_big_enough(enum_t *enume, type_t *base_type, return true; } -static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind) -{ - unsigned flags = get_atomic_type_flags(kind); - unsigned size = get_atomic_type_size(kind); - if (flags & ATOMIC_TYPE_FLAG_FLOAT) { - if (kind == ATOMIC_TYPE_LONG_DOUBLE && dialect.x87_long_double) { - assert(size == 12 || size == 16); - return new_float_mode("F80", irma_x86_extended_float, 15, 64, - target.float_int_overflow); - } - switch (size) { - case 4: - return new_float_mode("F32", irma_ieee754, 8, 23, - target.float_int_overflow); - case 8: - return new_float_mode("F64", irma_ieee754, 11, 52, - target.float_int_overflow); - case 16: - return new_float_mode("F128", irma_ieee754, 15, 112, - target.float_int_overflow); - default: panic("unexpected kind"); - } - } else if (flags & ATOMIC_TYPE_FLAG_INTEGER) { - char name[64]; - unsigned bit_size = size * 8; - bool is_signed = (flags & ATOMIC_TYPE_FLAG_SIGNED) != 0; - unsigned modulo_shift = decide_modulo_shift(bit_size); - - snprintf(name, sizeof(name), "%s%u", is_signed ? "I" : "U", bit_size); - return new_int_mode(name, bit_size, is_signed, modulo_shift); - } - - return NULL; -} - void init_constfold(void) { tarval_set_wrap_on_overflow(true); - const backend_params *be_params = be_get_backend_param(); - /* initialize modes for arithmetic types */ - memset(atomic_modes, 0, sizeof(atomic_modes)); - const ir_type *const type_ld = be_params->type_long_double; - if (type_ld != NULL) - atomic_modes[ATOMIC_TYPE_LONG_DOUBLE] = get_type_mode(type_ld); - mode_float_arithmetic = be_params->mode_float_arithmetic; - - for (int i = 0; i <= ATOMIC_TYPE_LAST; ++i) { - if (atomic_modes[i] != NULL) - continue; - atomic_modes[i] = init_atomic_ir_mode((atomic_type_kind_t) i); - } + mode_float_arithmetic = ir_target_float_arithmetic_mode(); + + ir_mode **m = atomic_modes; + m[ATOMIC_TYPE_BOOL] = ir_platform_type_mode(IR_TYPE_BOOL, false); + m[ATOMIC_TYPE_SCHAR] = ir_platform_type_mode(IR_TYPE_CHAR, true); + m[ATOMIC_TYPE_UCHAR] = ir_platform_type_mode(IR_TYPE_CHAR, false); + m[ATOMIC_TYPE_SHORT] = ir_platform_type_mode(IR_TYPE_SHORT, true); + m[ATOMIC_TYPE_USHORT] = ir_platform_type_mode(IR_TYPE_SHORT, false); + m[ATOMIC_TYPE_INT] = ir_platform_type_mode(IR_TYPE_INT, true); + m[ATOMIC_TYPE_UINT] = ir_platform_type_mode(IR_TYPE_INT, false); + m[ATOMIC_TYPE_LONG] = ir_platform_type_mode(IR_TYPE_LONG, true); + m[ATOMIC_TYPE_ULONG] = ir_platform_type_mode(IR_TYPE_LONG, false); + m[ATOMIC_TYPE_LONGLONG] = ir_platform_type_mode(IR_TYPE_LONG_LONG, true); + m[ATOMIC_TYPE_ULONGLONG] = ir_platform_type_mode(IR_TYPE_LONG_LONG, false); + m[ATOMIC_TYPE_FLOAT] = ir_platform_type_mode(IR_TYPE_FLOAT, true); + m[ATOMIC_TYPE_DOUBLE] = ir_platform_type_mode(IR_TYPE_DOUBLE, true); + m[ATOMIC_TYPE_LONG_DOUBLE] + = ir_platform_type_mode(IR_TYPE_LONG_DOUBLE, true); + m[ATOMIC_TYPE_CHAR] + = m[get_atomic_type_flags(ATOMIC_TYPE_CHAR) & ATOMIC_TYPE_FLAG_SIGNED + ? ATOMIC_TYPE_SCHAR : ATOMIC_TYPE_UCHAR]; + m[ATOMIC_TYPE_WCHAR_T] + = ir_platform_type_mode(ir_platform_wchar_type(), + ir_platform_wchar_is_signed()); } diff --git a/src/ast/dialect.h b/src/ast/dialect.h index beb9960..51a34fa 100644 --- a/src/ast/dialect.h +++ b/src/ast/dialect.h @@ -7,9 +7,6 @@ #include <stdbool.h> -#include "adt/util.h" -#include "ast/type.h" - #define BITS_PER_BYTE 8 typedef enum lang_features_t { @@ -23,31 +20,19 @@ typedef enum lang_features_t { } lang_features_t; typedef struct c_dialect_t { - atomic_type_kind_t wchar_atomic_kind; - atomic_type_kind_t pointer_sized_int; - atomic_type_kind_t pointer_sized_uint; - bool freestanding : 1; - bool no_builtins : 1; - bool char_is_signed : 1; - bool strict : 1; - bool c89 : 1; - bool c99 : 1; - bool c11 : 1; - bool cpp : 1; - bool gnu : 1; - bool ms : 1; - bool x87_long_double : 1; + bool freestanding : 1; + bool no_builtins : 1; + bool strict : 1; + bool c89 : 1; + bool c99 : 1; + bool c11 : 1; + bool cpp : 1; + bool gnu : 1; + bool ms : 1; /** enable hack to add call to __main into the main function (mingw) */ - bool enable_main_collect2_hack : 1; - bool support_fastcall_stdcall : 1; - unsigned char long_double_size; - unsigned char long_double_align; - unsigned char long_long_and_double_struct_align; - unsigned char long_long_size; - unsigned char int_size; - unsigned char pointer_size; - unsigned char long_size; - lang_features_t features; + bool enable_main_collect2_hack : 1; + bool support_fastcall_stdcall : 1; + lang_features_t features; } c_dialect_t; extern c_dialect_t dialect; diff --git a/src/ast/type.c b/src/ast/type.c index d97b2f1..ce1b76b 100644 --- a/src/ast/type.c +++ b/src/ast/type.c @@ -155,12 +155,7 @@ atomic_type_properties_t atomic_type_properties[ATOMIC_TYPE_LAST+1] = { .flags = ATOMIC_TYPE_FLAG_FLOAT | ATOMIC_TYPE_FLAG_SIGNED, .rank = 0, }, - [ATOMIC_TYPE_WCHAR_T] = { - .size = (unsigned)-1, - .alignment = (unsigned)-1, - .flags = ATOMIC_TYPE_FLAG_INTEGER, - .rank = (unsigned)-1, - }, + /* ATOMIC_TYPE_LONG_DOUBLE and ATOMIC_TYPE_WCHAR_T initialized later */ }; atomic_type_properties_t pointer_properties = { .size = 4, @@ -168,7 +163,10 @@ atomic_type_properties_t pointer_properties = { .flags = ATOMIC_TYPE_FLAG_NONE, }; -void init_types(unsigned int_size, unsigned long_size, unsigned pointer_size) +void init_types(unsigned int_size, unsigned long_size, unsigned pointer_size, + atomic_type_kind_t wchar_atomic_kind, + atomic_type_kind_t pointer_sized_int, + atomic_type_kind_t pointer_sized_uint) { obstack_init(&type_obst); @@ -186,13 +184,26 @@ void init_types(unsigned int_size, unsigned long_size, unsigned pointer_size) pointer_properties.alignment = pointer_size; props[ATOMIC_TYPE_LONG_DOUBLE] = props[ATOMIC_TYPE_DOUBLE]; - props[ATOMIC_TYPE_WCHAR_T] = props[ATOMIC_TYPE_INT]; /* set struct alignments to the same value as alignment */ for (size_t i = 0; i != ARRAY_SIZE(atomic_type_properties); ++i) { props[i].struct_alignment = props[i].alignment; } pointer_properties.struct_alignment = pointer_size; + + type_size_t = make_atomic_type(pointer_sized_uint, TYPE_QUALIFIER_NONE); + type_ssize_t = make_atomic_type(pointer_sized_int, TYPE_QUALIFIER_NONE); + type_uptrdiff_t = type_size_t; + type_ptrdiff_t = type_ssize_t; + + atomic_type_kind_t akind + = dialect.cpp ? ATOMIC_TYPE_WCHAR_T : wchar_atomic_kind; + type_wchar_t = make_atomic_type(akind, TYPE_QUALIFIER_NONE); + type_const_wchar_t = make_atomic_type(akind, TYPE_QUALIFIER_CONST); + type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE); + type_const_wchar_t_ptr + = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE); + props[ATOMIC_TYPE_WCHAR_T] = props[wchar_atomic_kind]; } void exit_types(void) diff --git a/src/ast/type.h b/src/ast/type.h index f08f237..1ef8039 100644 --- a/src/ast/type.h +++ b/src/ast/type.h @@ -76,7 +76,11 @@ typedef union type_t type_t; * to your system as your architecture and operating systems application binary * interface (ABI) requires. */ -void init_types(unsigned int_size, unsigned long_size, unsigned pointer_size); +void init_types(unsigned int_size, unsigned long_size, unsigned pointer_size, + atomic_type_kind_t wchar_atomic_kind, + atomic_type_kind_t pointer_sized_int, + atomic_type_kind_t pointer_sized_uint); + void exit_types(void); /** diff --git a/src/ast/types.c b/src/ast/types.c index 22217d4..abff7ce 100644 --- a/src/ast/types.c +++ b/src/ast/types.c @@ -198,20 +198,19 @@ void init_predefined_types(void) type_builtin_template_ptr = make_pointer_type(type_builtin_template, TYPE_QUALIFIER_NONE); - backend_params const *const be_params = be_get_backend_param(); - ir_type *be_va_list_type = be_params->va_list_type; - if (!be_va_list_type) { + ir_type *va_list_type = ir_platform_va_list_type(); + if (!va_list_type) { /* Backend has no vararg support. Just hope the the program will not be * using any. If it does, the parse_va_* functions will complain. */ type_valist = type_error_type; type_valist_arg = type_error_type; - } else if (is_Pointer_type(be_va_list_type)) { + } else if (is_Pointer_type(va_list_type)) { type_valist = type_void_ptr; type_valist_arg = type_void_ptr; - } else if (is_Struct_type(be_va_list_type)) { + } else if (is_Struct_type(va_list_type)) { entity_t *ent = allocate_entity_zero(ENTITY_STRUCT, NAMESPACE_NORMAL, sym_anonymous, &builtin_position); - ent->compound.alignment = get_type_alignment(be_va_list_type); - ent->compound.size = get_type_size(be_va_list_type); + ent->compound.alignment = get_type_alignment(va_list_type); + ent->compound.size = get_type_size(va_list_type); ent->compound.complete = true; ent->compound.members = (scope_t){ .first_entity = NULL, @@ -220,7 +219,7 @@ void init_predefined_types(void) }; type_t *type_valist_struct = allocate_type_zero(TYPE_COMPOUND_STRUCT); - type_valist_struct->base.firm_type = be_va_list_type; + type_valist_struct->base.firm_type = va_list_type; type_valist_struct->compound.compound = &ent->compound; type_valist = make_array_type(type_valist_struct, 1, TYPE_QUALIFIER_NONE); @@ -232,13 +231,6 @@ void init_predefined_types(void) type_const_char_ptr = make_pointer_type(type_const_char, TYPE_QUALIFIER_NONE); type_const_char_ptr_restrict = make_pointer_type(type_const_char, TYPE_QUALIFIER_RESTRICT); - atomic_type_kind_t pointer_sized_int = dialect.pointer_sized_int; - atomic_type_kind_t pointer_sized_uint = dialect.pointer_sized_uint; - type_size_t = make_atomic_type(pointer_sized_uint, TYPE_QUALIFIER_NONE); - type_ssize_t = make_atomic_type(pointer_sized_int, TYPE_QUALIFIER_NONE); - type_uptrdiff_t = type_size_t; - type_ptrdiff_t = type_ssize_t; - type_intmax_t = type_long_long; type_uintmax_t = type_unsigned_long_long; type_wint_t = type_unsigned_int; @@ -249,14 +241,6 @@ void init_predefined_types(void) type_ssize_t_ptr = make_pointer_type(type_ssize_t, TYPE_QUALIFIER_NONE); type_size_t_ptr = make_pointer_type(type_size_t, TYPE_QUALIFIER_NONE); - atomic_type_kind_t akind - = dialect.cpp ? ATOMIC_TYPE_WCHAR_T : dialect.wchar_atomic_kind; - type_wchar_t = make_atomic_type(akind, TYPE_QUALIFIER_NONE); - type_const_wchar_t = make_atomic_type(akind, TYPE_QUALIFIER_CONST); - type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE); - type_const_wchar_t_ptr - = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE); - atomic_type_kind_t const u2 = find_unsigned_int_atomic_type_kind_for_size(2); type_char16_t = make_atomic_type(u2, TYPE_QUALIFIER_NONE); type_char16_t_const = make_atomic_type(u2, TYPE_QUALIFIER_CONST); diff --git a/src/driver/actions.c b/src/driver/actions.c index 9ae5a80..5f0f8e5 100644 --- a/src/driver/actions.c +++ b/src/driver/actions.c @@ -4,12 +4,12 @@ */ #include "actions.h" -#include <libfirm/firm.h> +#include <libfirm/firm_common.h> +#include <libfirm/target.h> #include <stdio.h> #include <stdlib.h> #include "driver.h" -#include "machine_triple.h" #include "target.h" #include "version.h" #include <revision.h> @@ -44,8 +44,9 @@ int action_version_short(const char *argv0) int action_dumpmachine(const char *argv0) { (void)argv0; - machine_triple_t const *const machine = target.machine; - printf("%s-%s-%s\n", machine->cpu_type, machine->manufacturer, - machine->operating_system); + ir_machine_triple_t const *const machine = target.machine; + printf("%s-%s-%s\n", ir_triple_get_cpu_type(machine), + ir_triple_get_manufacturer(machine), + ir_triple_get_operating_system(machine)); return EXIT_SUCCESS; } diff --git a/src/driver/c_driver.c b/src/driver/c_driver.c index 4b40b9c..951a47a 100644 --- a/src/driver/c_driver.c +++ b/src/driver/c_driver.c @@ -79,8 +79,8 @@ bool print_phony_targets; const char *dependency_file; const char *dependency_target; bool dont_escape_target; -unsigned features_on; -unsigned features_off; +lang_features_t features_on; +lang_features_t features_off; lang_standard_t standard; const char *dumpfunction; const char *isysroot; @@ -809,8 +809,6 @@ bool do_nothing(compilation_env_t *env, compilation_unit_t *unit) static bool do_generate_code(FILE *asm_out, compilation_unit_t *unit) { - warn_experimental_target(); - ir_timer_t *t_opt_codegen = ir_timer_new(); timer_register(t_opt_codegen, "Optimization and Codegeneration"); timer_start(t_opt_codegen); diff --git a/src/driver/c_driver.h b/src/driver/c_driver.h index 04f05b7..76d6f01 100644 --- a/src/driver/c_driver.h +++ b/src/driver/c_driver.h @@ -6,6 +6,7 @@ #define C_DRIVER_H #include "driver.h" +#include "ast/dialect.h" typedef enum lang_standard_t { STANDARD_DEFAULT, /* gnu99 (for C, GCC does gnu89) or gnu++98 (for C++) */ @@ -27,8 +28,8 @@ extern struct obstack asflags_obst; extern struct obstack codegenflags_obst; extern struct obstack c_cpp_cppflags_obst; extern lang_standard_t standard; -extern unsigned features_on; -extern unsigned features_off; +extern lang_features_t features_on; +extern lang_features_t features_off; extern bool construct_dep_target; extern bool dump_defines; extern bool print_dependencies_instead_of_preprocessing; diff --git a/src/driver/help.c b/src/driver/help.c index 3225167..4955dfd 100644 --- a/src/driver/help.c +++ b/src/driver/help.c @@ -5,7 +5,7 @@ #include "help.h" #include <assert.h> -#include <libfirm/be.h> +#include <libfirm/target.h> #include <stdio.h> #include <stdlib.h> @@ -211,7 +211,6 @@ static void print_help_codegeneration(void) { help_spaced("-target", "TARGET", "Specify target architecture as CPU-manufacturer-OS triple"); help_equals("--target", "TARGET", "Same as -target TARGET"); - help_aprefix("-m", "OPTION", "Pass target specific option"); help_simple("-m16", "Select 16 bit variant of target architecture"); help_simple("-m32", "Select 32 bit variant of target architecture"); help_simple("-m64", "Select 64 bit variant of target architecture"); @@ -245,6 +244,7 @@ static void print_help_codegeneration(void) help_equals("-falign-loops", "ALIGNMENT", "Ignored (gcc compatibility)"); help_equals("-falign-jumps", "ALIGNEMNT", "Ignored (gcc compatibility)"); help_equals("-falign-functions", "ALIGNMENT", "Ignored (gcc compatibility)"); + help_aprefix("-m", "OPTION", "Directly pass option to libFirm backend"); puts(""); puts("\tMost of these options can be used with a no- prefix to disable them"); puts("\te.g. -fno-omit-frame-pointer"); @@ -298,10 +298,9 @@ static void print_help_language_tools(void) static void print_help_firm(void) { - help_simple("-bhelp", "Display firm codegeneration options"); - help_equals("-bisa", "ARCH", "Select architecture for firm backend"); - help_aprefix("-b", "OPTION", "Directly pass option to libFirm backend"); - int res = be_parse_arg("help"); + puts("libFirm backend options:"); + puts(""); + int res = ir_target_option("help"); (void) res; assert(res); } diff --git a/src/driver/machine_triple.c b/src/driver/machine_triple.c deleted file mode 100644 index 24fb27b..0000000 --- a/src/driver/machine_triple.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of cparser. - * Copyright (C) 2012 Matthias Braun <matze@braunis.de> - */ -#include <assert.h> -#include <stdbool.h> -#include "machine_triple.h" -#include "adt/strutil.h" -#include "adt/xmalloc.h" - -void free_machine_triple(machine_triple_t *machine) -{ - free(machine->cpu_type); - free(machine->manufacturer); - free(machine->operating_system); - free(machine); -} - -machine_triple_t *parse_machine_triple(const char *triple_string) -{ - const char *manufacturer = strchr(triple_string, '-'); - if (manufacturer == NULL) { - return NULL; - } - manufacturer += 1; - - const char *os = strchr(manufacturer, '-'); - if (os != NULL) { - 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 */ - - const char *cpu = triple_string; - - machine_triple_t *triple = XMALLOCZ(machine_triple_t); - - size_t cpu_type_len = manufacturer-cpu; - triple->cpu_type = XMALLOCN(char, cpu_type_len); - memcpy(triple->cpu_type, cpu, cpu_type_len-1); - triple->cpu_type[cpu_type_len-1] = '\0'; - - /* process manufacturer, alot of people incorrectly leave out the - * manufacturer instead of using unknown- */ - if (strstart(manufacturer, "linux") || streq(manufacturer, "elf") - || os == NULL) { - triple->manufacturer = xstrdup("unknown"); - os = manufacturer; - } else { - size_t manufacturer_len = os-manufacturer; - triple->manufacturer = XMALLOCN(char, manufacturer_len); - memcpy(triple->manufacturer, manufacturer, manufacturer_len-1); - triple->manufacturer[manufacturer_len-1] = '\0'; - } - - triple->operating_system = xstrdup(os); - return triple; -} diff --git a/src/driver/machine_triple.h b/src/driver/machine_triple.h deleted file mode 100644 index 1e39292..0000000 --- a/src/driver/machine_triple.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is part of cparser. - * Copyright (C) 2012 Matthias Braun <matze@braunis.de> - */ -#ifndef FIRM_MACHINE_H -#define FIRM_MACHINE_H - -#include <stdbool.h> - -typedef struct machine_triple_t { - char *cpu_type; - char *manufacturer; - char *operating_system; -} machine_triple_t; - -machine_triple_t *parse_machine_triple(const char *triple_string); - -void free_machine_triple(machine_triple_t *triple); - -#endif diff --git a/src/driver/options.c b/src/driver/options.c index 0daab06..8fccb69 100644 --- a/src/driver/options.c +++ b/src/driver/options.c @@ -382,7 +382,7 @@ bool options_parse_linker(options_state_t *s) driver_add_flag(&ldflags_obst, "-Xlinker"); driver_add_flag(&ldflags_obst, arg); } else if (simple_arg("pg", s)) { - set_be_option("gprof"); + set_target_option("gprof"); driver_add_flag(&ldflags_obst, "-pg"); } else if ((arg = equals_arg("print-file-name", s)) != NULL) { print_file_name_file = arg; @@ -432,18 +432,6 @@ bool options_parse_codegen(options_state_t *s) } 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)) { @@ -451,11 +439,11 @@ bool options_parse_codegen(options_state_t *s) * 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"); + set_target_option("debug=none"); + set_target_option("ia32-optcc=true"); } else { - set_be_option("debug=frameinfo"); - set_be_option("ia32-optcc=false"); + set_target_option("debug=frameinfo"); + set_target_option("ia32-optcc=false"); } } else if (accept_prefix(s, "-m", false, &arg)) { arg = &option[1]; @@ -476,7 +464,8 @@ bool options_parse_codegen(options_state_t *s) 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"); + target.set_use_frame_pointer = true; + target.use_frame_pointer = truth_value; } else if (f_yesno_arg("-fstrength-reduce", s)) { /* does nothing, for gcc compatibility (even gcc does * nothing for this switch anymore) */ @@ -489,13 +478,20 @@ bool options_parse_codegen(options_state_t *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"); + set_target_option(truth_value ? "verboseasm" : "verboseasm=no"); } else if (f_yesno_arg("-fPIC", s)) { - target.pic_mode = truth_value ? 2 : 0; + target.pic = truth_value; + target.set_pic = true; } else if (f_yesno_arg("-fpic", s)) { - target.pic_mode = truth_value ? 1 : 0; + target.pic = truth_value; + target.set_pic = true; + /* cparser has no concept of -fPIC vs. -fpic yet */ + if (truth_value) + warningf(WARN_COMPAT_OPTION, NULL, + "-fpic unsupported, using -fPIC instead"); } else if (f_yesno_arg("-fplt", s)) { - target.pic_no_plt = !truth_value; + target.pic_noplt = !truth_value; + target.set_noplt = true; } else if (f_yesno_arg("-fjump-tables", s) || f_yesno_arg("-fexpensive-optimizations", s) || f_yesno_arg("-fcommon", s) || @@ -595,12 +591,12 @@ bool options_parse_c_dialect(options_state_t *s) const char *fopt; if ((fopt = f_no_arg(&truth_value, s)) != NULL) { if (f_yesno_arg("-fshort-wchar", s)) { - dialect.wchar_atomic_kind = truth_value ? ATOMIC_TYPE_USHORT - : ATOMIC_TYPE_INT; + set_wchar = true; + short_wchar = truth_value; } else if (f_yesno_arg("-fsigned-char", s)) { - dialect.char_is_signed = truth_value; + unsigned_char = !truth_value; } else if (f_yesno_arg("-funsigned-char", s)) { - dialect.char_is_signed = !truth_value; + unsigned_char = truth_value; } else if (f_yesno_arg("-ffreestanding", s)) { dialect.freestanding = truth_value; dialect.no_builtins = truth_value; @@ -628,9 +624,6 @@ bool options_parse_help(options_state_t *s) fprintf(stderr, "warning: -fhelp is deprecated (use --help-optimization)\n"); help |= HELP_OPTIMIZATION; - } else if (simple_arg("bhelp", s)) { - fprintf(stderr, "warning: -bhelp is deprecated (use --help-firm)\n"); - help |= HELP_FIRM; } else if (simple_arg("-help", s)) { help |= HELP_BASIC; } else if (simple_arg("-help-preprocessor", s)) { @@ -662,7 +655,7 @@ bool options_parse_help(options_state_t *s) static bool parse_target_triple(const char *arg) { - machine_triple_t *triple = parse_machine_triple(arg); + ir_machine_triple_t *triple = ir_parse_machine_triple(arg); if (triple == NULL) { errorf(NULL, "target-triple '%s' is not in the form 'cpu_type-manufacturer-operating_system'", arg); return false; diff --git a/src/driver/predefs.c b/src/driver/predefs.c index a217ad9..b0deef2 100644 --- a/src/driver/predefs.c +++ b/src/driver/predefs.c @@ -15,7 +15,6 @@ #include "ast/types.h" #include "firm/ast2firm.h" #include "firm/firm_opt.h" -#include "machine_triple.h" #include "parser/preprocessor.h" #include "target.h" #include "version.h" @@ -308,12 +307,6 @@ void add_predefined_macros(void) /* no support for the XXX_chk functions in cparser yet */ add_define("_FORTIFY_SOURCE", "0", false); - switch (target.object_format) { - case OBJECT_FORMAT_ELF: add_define("__ELF__", "1", false); break; - case OBJECT_FORMAT_PE_COFF: add_define("__PE__", "1", false); break; - case OBJECT_FORMAT_MACH_O: break; - } - add_define("__ORDER_BIG_ENDIAN__", "4321", false); add_define("__ORDER_LITTLE_ENDIAN__", "1234", false); add_define("__ORDER_PDP_ENDIAN__", "3412", false); @@ -336,7 +329,7 @@ void add_predefined_macros(void) add_define("__ILP32__", "1", false); } - ir_mode *float_mode = be_get_mode_float_arithmetic(); + ir_mode *float_mode = ir_target_float_arithmetic_mode(); const char *flt_eval_metod = float_mode == NULL ? "0" : get_mode_size_bytes(float_mode) > get_ctype_size(type_double) ? "2" @@ -344,11 +337,6 @@ void add_predefined_macros(void) : "-1"; add_define("__FLT_EVAL_METHOD__", flt_eval_metod, false); - if (target.pic_mode != 0) { - add_define_int("__PIC__", target.pic_mode); - add_define_int("__pic__", target.pic_mode); - } - char user_label_prefix_str[] = { target.user_label_prefix, '\0' }; add_define("__USER_LABEL_PREFIX__", user_label_prefix_str, false); add_define("__REGISTER_PREFIX__", "", false); @@ -462,10 +450,12 @@ void add_predefined_macros(void) /* TODO: __CHAR16_TYPE__, __CHAR32_TYPE__ */ /* Add target specific defines */ - for (const target_define_t *define = target.defines; define != NULL; - define = define->next) { - if (define->condition != NULL && !define->condition()) + for (ir_platform_define_t const *define = ir_platform_define_first(); + define != NULL; define = ir_platform_define_next(define)) { + char const *const name = ir_platform_define_name(define); + if (name[0] != '_' && !dialect.gnu) continue; - add_define(define->name, define->value, false); + char const *const value = ir_platform_define_value(define); + add_define(name, value, false); } } diff --git a/src/driver/target.c b/src/driver/target.c index c8bc8f3..a02ae33 100644 --- a/src/driver/target.c +++ b/src/driver/target.c @@ -19,48 +19,82 @@ #include "target.h" #include "warning.h" -target_t target = { - .biggest_alignment = 16, - .pic_mode = -1, -}; +target_t target; + const char *multilib_directory_target_triple; unsigned target_size_override; +bool set_wchar; +bool short_wchar; +bool unsigned_char; -void target_adjust_types_and_dialect(void) +static atomic_type_kind_t ir_platform_to_ast(ir_platform_type_t type, + bool get_signed) { - init_types(dialect.int_size, dialect.long_size, dialect.pointer_size); - - atomic_type_properties_t *props = atomic_type_properties; + switch (type) { + case IR_TYPE_BOOL: + return ATOMIC_TYPE_BOOL; + case IR_TYPE_CHAR: + return get_signed ? ATOMIC_TYPE_SCHAR : ATOMIC_TYPE_UCHAR; + case IR_TYPE_SHORT: + return get_signed ? ATOMIC_TYPE_SHORT : ATOMIC_TYPE_USHORT; + case IR_TYPE_INT: + return get_signed ? ATOMIC_TYPE_INT : ATOMIC_TYPE_UINT; + case IR_TYPE_LONG: + return get_signed ? ATOMIC_TYPE_LONG : ATOMIC_TYPE_ULONG; + case IR_TYPE_LONG_LONG: + return get_signed ? ATOMIC_TYPE_LONGLONG : ATOMIC_TYPE_ULONGLONG; + case IR_TYPE_FLOAT: + assert(get_signed); + return ATOMIC_TYPE_FLOAT; + case IR_TYPE_DOUBLE: + assert(get_signed); + return ATOMIC_TYPE_DOUBLE; + case IR_TYPE_LONG_DOUBLE: + assert(get_signed); + return ATOMIC_TYPE_LONG_DOUBLE; + } + panic("Invalid basic type"); +} - /* Adjustments for some systems */ - props[ATOMIC_TYPE_LONGLONG].size = dialect.long_long_size; - props[ATOMIC_TYPE_LONGLONG].alignment = dialect.long_long_size; - props[ATOMIC_TYPE_LONGLONG].struct_alignment = dialect.long_long_size; - props[ATOMIC_TYPE_ULONGLONG].size = dialect.long_long_size; - props[ATOMIC_TYPE_ULONGLONG].alignment = dialect.long_long_size; - props[ATOMIC_TYPE_ULONGLONG].struct_alignment = dialect.long_long_size; +void target_adjust_types_and_dialect(void) +{ + unsigned int_size = ir_platform_type_size(IR_TYPE_INT); + unsigned long_size = ir_platform_type_size(IR_TYPE_LONG); + unsigned pointer_size = ir_target_pointer_size(); + atomic_type_kind_t pointer_sized_int + = ir_platform_to_ast(ir_platform_intptr_type(), true); + atomic_type_kind_t pointer_sized_uint + = ir_platform_to_ast(ir_platform_intptr_type(), false); + atomic_type_kind_t wchar_atomic_kind + = set_wchar ? (short_wchar ? ATOMIC_TYPE_USHORT : ATOMIC_TYPE_INT) + : ir_platform_to_ast(ir_platform_wchar_type(), + ir_platform_wchar_is_signed()); + init_types(int_size, long_size, pointer_size, wchar_atomic_kind, + pointer_sized_int, pointer_sized_uint); + + atomic_type_properties_t *const props = atomic_type_properties; unsigned const ll_d_struct_align - = dialect.long_long_and_double_struct_align; + = ir_platform_long_long_and_double_struct_align_override(); if (ll_d_struct_align > 0) { props[ATOMIC_TYPE_LONGLONG].struct_alignment = ll_d_struct_align; props[ATOMIC_TYPE_ULONGLONG].struct_alignment = ll_d_struct_align; props[ATOMIC_TYPE_DOUBLE].struct_alignment = ll_d_struct_align; } - props[ATOMIC_TYPE_LONG_DOUBLE].size = dialect.long_double_size; - props[ATOMIC_TYPE_LONG_DOUBLE].alignment = dialect.long_double_align; - props[ATOMIC_TYPE_LONG_DOUBLE].struct_alignment = dialect.long_double_align; + props[ATOMIC_TYPE_LONG_DOUBLE].size + = ir_platform_type_size(IR_TYPE_LONG_DOUBLE); + unsigned align = ir_platform_type_align(IR_TYPE_LONG_DOUBLE); + props[ATOMIC_TYPE_LONG_DOUBLE].alignment = align; + props[ATOMIC_TYPE_LONG_DOUBLE].struct_alignment = align; /* stuff decided after processing operating system specifics and * commandline flags */ - if (dialect.char_is_signed) { - props[ATOMIC_TYPE_CHAR].flags |= ATOMIC_TYPE_FLAG_SIGNED; - } else { + if (unsigned_char) { props[ATOMIC_TYPE_CHAR].flags &= ~ATOMIC_TYPE_FLAG_SIGNED; + } else { + props[ATOMIC_TYPE_CHAR].flags |= ATOMIC_TYPE_FLAG_SIGNED; } - /* copy over wchar_t properties (including rank) */ - props[ATOMIC_TYPE_WCHAR_T] = props[dialect.wchar_atomic_kind]; static bool had_cpp_warning; if (dialect.cpp && !had_cpp_warning) { @@ -69,77 +103,21 @@ void target_adjust_types_and_dialect(void) had_cpp_warning = true; } - if (target.firm_isa_specified) { - backend_params const *const p = be_get_backend_param(); - target.float_int_overflow = p->float_int_overflow; - target.byte_order_big_endian = p->byte_order_big_endian; - dialect.pointer_size = p->machine_size / BITS_PER_BYTE; - } else { - /* The frontend should do all decisions and should not be influenced by - * outside influences like the firm backend. So we just check here that - * our decisions match the firm backend. */ - assert(be_get_backend_param()->machine_size % BITS_PER_BYTE == 0); - assert(dialect.pointer_size - == be_get_backend_param()->machine_size / BITS_PER_BYTE); - assert(target.byte_order_big_endian - == be_get_backend_param()->byte_order_big_endian); - assert(target.float_int_overflow - == be_get_backend_param()->float_int_overflow); - } -} - -static ident *compilerlib_name_mangle(ident *id, ir_type *mt) -{ - (void)mt; - char const prefix = target.user_label_prefix; - if (prefix == '\0') - return id; /* Shortcut for empty prefix */ - return new_id_fmt("%c%s", prefix, id); -} - -/** Add a target specific preprocessor define. */ -static target_define_t *ppdef(const char *name, const char *value) -{ - target_define_t *define = XMALLOCZ(target_define_t); - define->name = name; - define->value = value; - define->next = target.defines; - target.defines = define; - return define; -} - -/** Add a target specific preprocessor define. This calls \p condition_func - * to check whether the define should really be added. */ -static target_define_t *ppdefc(const char *name, const char *value, - bool (*condition_func)(void)) -{ - target_define_t *define = ppdef(name, value); - define->condition = condition_func; - return define; -} - -static bool cond_not_strict(void) -{ - return dialect.gnu; -} - -static bool cond_is_little_endian(void) -{ - return !target.byte_order_big_endian; -} - -static void init_generic_elf(void) -{ - driver_default_exe_output = "a.out"; - target.object_format = OBJECT_FORMAT_ELF; - set_be_option("ia32-struct_in_reg=no"); -} - -static void init_unix(void) -{ - ppdef( "__unix", "1"); - ppdef( "__unix__", "1"); - ppdefc("unix", "1", cond_not_strict); + /* Check that we match libfirms view of the world */ + assert(ir_platform_type_size(IR_TYPE_BOOL) == props[ATOMIC_TYPE_BOOL].size); + assert(ir_platform_type_size(IR_TYPE_CHAR) == props[ATOMIC_TYPE_CHAR].size); + assert(ir_platform_type_size(IR_TYPE_SHORT) + == props[ATOMIC_TYPE_SHORT].size); + assert(ir_platform_type_size(IR_TYPE_INT) == props[ATOMIC_TYPE_INT].size); + assert(ir_platform_type_size(IR_TYPE_LONG) == props[ATOMIC_TYPE_LONG].size); + assert(ir_platform_type_size(IR_TYPE_LONG_LONG) + == props[ATOMIC_TYPE_LONGLONG].size); + assert(ir_platform_type_size(IR_TYPE_FLOAT) + == props[ATOMIC_TYPE_FLOAT].size); + assert(ir_platform_type_size(IR_TYPE_DOUBLE) + == props[ATOMIC_TYPE_DOUBLE].size); + assert(ir_platform_type_size(IR_TYPE_LONG_DOUBLE) + == props[ATOMIC_TYPE_LONG_DOUBLE].size); } static bool is_ia32_cpu(const char *cpu) @@ -154,313 +132,51 @@ static bool is_amd64_cpu(char const *const cpu) return streq(cpu, "x86_64") || streq(cpu, "amd64"); } -static void set_options_for_machine(machine_triple_t const *const machine) +void set_target_option(char const *const arg) { - /* 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 long_double_align; - 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; - long_double_align = 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; - long_double_align = 4; - 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.x87_long_double = 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; - long_double_align = 8; - float_int_overflow = ir_overflow_min_max; - target.byte_order_big_endian = true; - target.biggest_alignment = 8; - } 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; - long_double_align = 8; - float_int_overflow = ir_overflow_min_max; - target.biggest_alignment = 8; - } 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; - long_double_align = 16; - float_int_overflow = ir_overflow_indefinite; - dialect.x87_long_double = true; - } else if (streq(cpu, "mips")) { - ppdef("__mips__", "1"); - firm_isa = "mips"; - pointer_size = 4; - modulo_shift = 32; - long_double_size = 8; - long_double_align = 8; - float_int_overflow = ir_overflow_indefinite; - target.byte_order_big_endian = true; - target.biggest_alignment = 8; - } 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.long_double_align = long_double_align; - 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 (strstart(os, "freebsd")) { - ppdef( "__FreeBSD__", ""); - goto bsd; - } else if (strstr(os, "bsd") != NULL) { -bsd: - init_generic_elf(); - init_unix(); - set_be_option("ia32-struct_in_reg=yes"); - } 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"; - 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; - dialect.long_double_align = 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"); - 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); - target.user_label_prefix = '_'; - dialect.pointer_sized_int = ATOMIC_TYPE_INT; - dialect.pointer_sized_uint = ATOMIC_TYPE_UINT; - dialect.support_fastcall_stdcall = true; - } - } 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"); - ppdef("__NT64", "1"); - } else { - assert(pointer_size == 4); - target.user_label_prefix = '_'; - ppdef("__NT32", "1"); - } - } else { - errorf(NULL, "unknown operating system '%s' in target-triple", os); - exit(EXIT_FAILURE); - } -} - -void warn_experimental_target(void) -{ - char const *const experimental = be_get_backend_param()->experimental; - if (experimental) - warningf(WARN_EXPERIMENTAL, NULL, "%s", experimental); -} - -static bool setup_firm_isa(void) -{ - const char *isa = target.firm_isa; - char buf[64]; - snprintf(buf, sizeof(buf), "isa=%s", isa); - if (!be_parse_arg(buf)) { - errorf(NULL, "Couldn't select firm isa '%s'", isa); - return false; - } - - const char *arch = target.firm_arch; - /* only pass down for ia32 for now */ - if (arch != NULL && streq(isa, "ia32")) { - snprintf(buf, sizeof(buf), "%s-arch=%s", isa, arch); - if (!be_parse_arg(buf)) { - errorf(NULL, "Couldn't select firm arch '%s-arch=%s'", isa, arch); - return false; - } - } - - return true; + int res = ir_target_option(arg); + if (!res) + panic("setting firm backend option '%s' failed (maybe an outdated version of firm is used)", arg); } 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; - } +#ifdef NO_DEFAULT_VERIFY + set_target_option("verify=off"); +#endif if (profile_generate) { driver_add_flag(&ldflags_obst, "-lfirmprof"); - set_be_option("profilegenerate"); + set_target_option("profilegenerate"); } if (profile_use) { - set_be_option("profileuse"); + set_target_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"; + if (target.set_use_frame_pointer) { + set_target_option(target.use_frame_pointer ? "omitfp" : "omitfp=no"); + } + + if (target.set_pic) { + if (target.pic && !ir_target_supports_pic()) { + errorf(NULL, + "Position independent code (PIC) not supported by target"); + exit(EXIT_FAILURE); } - } else { - pic_option = "pic=none"; - target.pic_mode = 0; + + set_target_option(target.pic ? "pic=1" : "pic=0"); } - set_be_option(pic_option); + if (target.set_noplt) + set_target_option(target.pic_noplt ? "noplt=1" : "noplt=0"); /* pass options to firm backend (this happens delayed because we first * had to decide which backend is actually used) */ + bool res = true; 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); + /* pass option along to firm backend (except the ones already filtered + * out like -m32, -m64) */ + if (!ir_target_option(option->option)) { + errorf(NULL, "Unknown codegen option '-m%s'", option->option); res = false; continue; } @@ -472,6 +188,7 @@ static bool pass_options_to_firm_be(void) }; for (size_t i = 0; i < ARRAY_SIZE(pass_to_cpp_and_ld); ++i) { if (streq(pass_to_cpp_and_ld[i], option->option)) { + char buf[64]; snprintf(buf, sizeof(buf), "-m%s", option->option); driver_add_flag(&cppflags_obst, buf); driver_add_flag(&asflags_obst, buf); @@ -481,113 +198,76 @@ static bool pass_options_to_firm_be(void) } } - /* 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 machine_triple_t *get_host_machine_triple(void) -{ -#ifdef HOST_TRIPLE - /* a triple for the host machine was defined in the Makefile - * or config.mak */ - return parse_machine_triple(HOST_TRIPLE); -#else - /* no host triple specified, we do some guessing based on preprocessor - * defines (look into predefs.c for inspiration) */ - machine_triple_t *machine = XMALLOC(machine_triple_t); - - machine->cpu_type = xstrdup( -#if defined(__x86_64__) - "x86_64" -#elif defined(__i686__) - "i686" -#elif defined(__i386__) - "i386" -#elif defined(__sparc__) - "sparc" -#elif defined(__arm__) - "arm" -#else - /* Choose a widely used cpu_type; "unknown" would not be useful here. */ - "i386" -#endif - ); - - machine->manufacturer = xstrdup( -#if defined(__leon__) - "leon" -#else - "unknown" -#endif - ); - - machine->operating_system = xstrdup( -#if defined(_WIN32) || defined(__CYGWIN__) - "win32" -#elif defined(__APPLE__) - "darwin" -#elif defined(__FreeBSD__) - "freebsd" -#elif defined(__gnu_linux__) - "linux-gnu" -#elif defined(__linux__) - "linux" -#elif defined(__midipix__) - "midipix" -#elif defined(__ELF__) - "elf" -#else - "unknown" -#endif - ); - - return machine; -#endif -} - static void determine_target_machine(void) { if (target.machine == NULL) - target.machine = get_host_machine_triple(); + target.machine = ir_get_host_machine_triple(); /* adjust for -m32/-m64 flag */ - const char *cpu = target.machine->cpu_type; + const char *cpu = ir_triple_get_cpu_type(target.machine); if (is_ia32_cpu(cpu) && target_size_override == 64) { - free(target.machine->cpu_type); - target.machine->cpu_type = xstrdup("x86_64"); + ir_triple_set_cpu_type(target.machine, "x86_64"); } else if (is_amd64_cpu(cpu) && target_size_override == 32) { - free(target.machine->cpu_type); - target.machine->cpu_type = xstrdup("i686"); + ir_triple_set_cpu_type(target.machine, "i686"); + } +} + +static void set_options_from_be(void) +{ + if (target.pic && !ir_target_supports_pic()) { + errorf(NULL, "Position independent code (PIC) not supported by target"); + exit(EXIT_FAILURE); + } + + target.biggest_alignment = ir_target_biggest_alignment(); + target.user_label_prefix = ir_platform_user_label_prefix(); + target.byte_order_big_endian = ir_target_big_endian(); + driver_default_exe_output = ir_platform_default_exe_name(); + + if (strstart(ir_triple_get_operating_system(target.machine), "mingw")) { + /* TODO: This should be done by libfirm instead of modifying the AST */ + dialect.enable_main_collect2_hack = true; + + if (ir_target_pointer_size() == 4) + dialect.support_fastcall_stdcall = true; } } -void target_set_defaults(void) +void init_firm_target(void) { + ir_init_library(); determine_target_machine(); - set_options_for_machine(target.machine); + + bool initialized = ir_target_set_triple(target.machine); + if (!initialized) { + errorf(NULL, "Failed to initialize libfirm code generation\n"); + exit(EXIT_FAILURE); + } } bool target_setup(void) { - bool res = setup_firm_isa(); - res &= pass_options_to_firm_be(); + bool res = pass_options_to_firm_be(); + if (!res) + return false; multilib_directory_target_triple = NULL; if (target.triple == NULL) { #ifdef MULTILIB_M32_TRIPLE - if (dialect.pointer_size == 4) + if (ir_target_pointer_size() == 4) multilib_directory_target_triple = MULTILIB_M32_TRIPLE; #endif #ifdef MULTILIB_M64_TRIPLE - if (dialect.pointer_size == 8) + if (ir_target_pointer_size() == 8) multilib_directory_target_triple = MULTILIB_M64_TRIPLE; #endif } + ir_target_init(); + + set_options_from_be(); + return res; } diff --git a/src/driver/target.h b/src/driver/target.h index 1d9035d..9f42132 100644 --- a/src/driver/target.h +++ b/src/driver/target.h @@ -7,67 +7,39 @@ #include <stdbool.h> #include <libfirm/irmode.h> +#include <libfirm/target.h> #include "adt/util.h" -#include "machine_triple.h" #include "firm/firm_opt.h" #include "options.h" -typedef enum object_format_t { - OBJECT_FORMAT_ELF, - OBJECT_FORMAT_MACH_O, - OBJECT_FORMAT_PE_COFF, -} object_format_t; - -/** - * Name+Value of a target specific preprocessor define. This is necessary to - * avoid doing target specific decisions outside of target.c - */ -typedef struct target_define_t target_define_t; -struct target_define_t { - char const *name; - char const *value; - target_define_t *next; - bool (*condition)(void); -}; - typedef struct target_t { - /** - * whether architecture shift instructions usually perform modulo bit_size - * on the shift amount, if yes this equals to the machine_size. - */ - unsigned int modulo_shift; - float_int_conversion_overflow_style_t float_int_overflow; - char user_label_prefix; - unsigned char biggest_alignment; - /** position independent code generation mode */ - int pic_mode : 4; - bool pic_no_plt : 1; - /** byte-order: true = big-endian, false = little-endian */ + char user_label_prefix; + unsigned char biggest_alignment; + bool pic : 1; + bool set_pic : 1; + bool pic_noplt : 1; + bool set_noplt : 1; bool byte_order_big_endian : 1; - /** firm_isa was explicitely specified on the commandline */ - bool firm_isa_specified : 1; - ENUMBF(object_format_t) object_format : 2; - target_define_t *defines; - const char *firm_isa; - const char *firm_arch; + bool set_use_frame_pointer : 1; + bool use_frame_pointer : 1; /** parsed machine-triple of target machine. Try not to use this if possible * but create specific variables for language/target features instead. */ - machine_triple_t *machine; + ir_machine_triple_t *machine; /** target triple as a string */ - const char *triple; + const char *triple; } target_t; extern target_t target; -void target_set_defaults(void); +void init_firm_target(void); bool target_setup(void); -void warn_experimental_target(void); void target_adjust_types_and_dialect(void); -typedef struct codegen_option_t codegen_option_t; +void set_target_option(char const *arg); +typedef struct codegen_option_t codegen_option_t; struct codegen_option_t { codegen_option_t *next; char option[]; @@ -80,5 +52,8 @@ extern bool profile_generate; extern bool profile_use; extern const char *multilib_directory_target_triple; extern unsigned target_size_override; +extern bool set_wchar; +extern bool short_wchar; +extern bool unsigned_char; #endif diff --git a/src/firm/ast2firm.c b/src/firm/ast2firm.c index 1466beb..065797b 100644 --- a/src/firm/ast2firm.c +++ b/src/firm/ast2firm.c @@ -6,7 +6,6 @@ #include <assert.h> #include <libfirm/adt/obst.h> -#include <libfirm/be.h> #include <libfirm/firm.h> #include <stdbool.h> #include <string.h> @@ -2185,8 +2184,7 @@ static ir_node *va_start_expression_to_firm(const va_start_expression_t *const e dbg_info *const dbgi = get_dbg_info(&expr->base.pos); ir_node *const memory = get_store(); - backend_params const *const be_params = be_get_backend_param(); - ir_type *va_list_type = be_params->va_list_type; + ir_type *va_list_type = ir_platform_va_list_type(); if (is_Pointer_type(va_list_type)) { /* The backend implements va_list as a single pointer. The initial value of @@ -2229,8 +2227,7 @@ static ir_node *va_arg_expression_to_firm(const va_arg_expression_t *const expr) if (!resmode) resmode = mode_P; - backend_params const *const be_params = be_get_backend_param(); - ir_type *va_list_type = be_params->va_list_type; + ir_type *va_list_type = ir_platform_va_list_type(); if (is_Pointer_type(va_list_type)) { /* va_arg takes the old pointer as argument and returns the current argument @@ -2283,10 +2280,9 @@ static ir_node *va_arg_expression_to_firm(const va_arg_expression_t *const expr) */ static ir_node *va_copy_expression_to_firm(const va_copy_expression_t *const expr) { - ir_node *const src = expression_to_value(expr->src); - backend_params const *const be_params = be_get_backend_param(); - ir_type *const va_list_type = be_params->va_list_type; - dbg_info *const dbgi = get_dbg_info(&expr->base.pos); + ir_node *const src = expression_to_value(expr->src); + ir_type *const va_list_type = ir_platform_va_list_type(); + dbg_info *const dbgi = get_dbg_info(&expr->base.pos); if (is_Pointer_type(va_list_type)) { set_value_for_expression_addr(expr->dst, src, NULL); @@ -4026,7 +4022,7 @@ static void create_local_variable(entity_t *entity) static ir_type *get_glob_var_type(entity_t const *const entity) { if (entity->variable.thread_local) { - if (!be_get_backend_param()->thread_local_storage_supported) { + if (!ir_platform_supports_thread_local_storage()) { errorf(&entity->base.pos, "Thread local storage not supported by backend"); } diff --git a/src/firm/firm_opt.c b/src/firm/firm_opt.c index c897423..4715c5a 100644 --- a/src/firm/firm_opt.c +++ b/src/firm/firm_opt.c @@ -19,6 +19,8 @@ #include "adt/panic.h" #include "adt/strutil.h" #include "adt/util.h" +#include "driver/diagnostic.h" +#include "driver/target.h" #include "driver/timing.h" /* optimization settings */ @@ -684,22 +686,10 @@ static void do_firm_lowering(void) dump_all("low-opt"); } -void set_be_option(char const *const arg) -{ - int res = be_parse_arg(arg); - if (!res) - panic("setting firm backend option '%s' failed (maybe an outdated version of firm is used)", arg); -} - void init_firm_opt(void) { - ir_init(); enable_safe_defaults(); -#ifdef NO_DEFAULT_VERIFY - set_be_option("verify=off"); -#endif - FOR_EACH_OPT(i) { i->timer = ir_timer_new(); timer_register(i->timer, i->description); @@ -765,6 +755,10 @@ void optimize_lower_ir_prog(void) */ void generate_code(FILE *out, const char *input_filename) { + char const *const experimental = ir_target_experimental(); + if (experimental) + warningf(WARN_EXPERIMENTAL, NULL, "%s", experimental); + optimize_lower_ir_prog(); /* run the code generator */ @@ -906,7 +900,8 @@ void set_optimization_level(optimization_level_t level) set_option("occults"); set_option("deconv"); set_option("memcombine"); - set_be_option("omitfp"); + target.set_use_frame_pointer = true; + target.use_frame_pointer = false; return; case OPT_s: diff --git a/src/firm/firm_opt.h b/src/firm/firm_opt.h index 4303124..15fdbe4 100644 --- a/src/firm/firm_opt.h +++ b/src/firm/firm_opt.h @@ -144,6 +144,4 @@ void set_optimization_level(optimization_level_t opt_level); */ void init_implicit_optimizations(void); -void set_be_option(char const *arg); - #endif @@ -310,7 +310,6 @@ int main(int argc, char **argv) init_driver(); init_default_driver(); init_preprocessor(); - init_firm_opt(); /* initialize early because we need to parse options */ init_ast(); init_parser(); @@ -331,8 +330,9 @@ int main(int argc, char **argv) if (!isysroot) isysroot = lsysroot; - /* Setup target so later options can override the target defaults */ - target_set_defaults(); + /* Initialize firm now that we know the target machine */ + init_firm_target(); + init_firm_opt(); set_optimization_level(opt_level); /* parse rest of options */ |