summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2017-01-01 18:48:49 +0100
committerMatthias Braun <matze@braunis.de>2017-02-20 04:48:33 +0100
commit1e671622e9015458d90974b4ed8a14fecb166bc1 (patch)
tree986b0abe992d111ca9ef5b5eedac029611d594a8 /src
parentd35d57ebf0d828a43e700358f0a011a27ce1c31b (diff)
Use new libfirm target API
This moves the target and platform knowledge and initialization into libfirm.
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.c6
-rw-r--r--src/ast/constfold.c79
-rw-r--r--src/ast/dialect.h39
-rw-r--r--src/ast/type.c27
-rw-r--r--src/ast/type.h6
-rw-r--r--src/ast/types.c30
-rw-r--r--src/driver/actions.c11
-rw-r--r--src/driver/c_driver.c6
-rw-r--r--src/driver/c_driver.h5
-rw-r--r--src/driver/help.c11
-rw-r--r--src/driver/machine_triple.c60
-rw-r--r--src/driver/machine_triple.h20
-rw-r--r--src/driver/options.c53
-rw-r--r--src/driver/predefs.c24
-rw-r--r--src/driver/target.c606
-rw-r--r--src/driver/target.h59
-rw-r--r--src/firm/ast2firm.c16
-rw-r--r--src/firm/firm_opt.c21
-rw-r--r--src/firm/firm_opt.h2
-rw-r--r--src/main.c6
20 files changed, 291 insertions, 796 deletions
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
diff --git a/src/main.c b/src/main.c
index f06c178..17958ab 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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 */