/* * This file is part of libFirm. * Copyright (C) 2017 University of Karlsruhe. */ #include "target_t.h" #include "be_t.h" #include "iropt_t.h" #include "irtools.h" #include "isas.h" #include "lc_opts.h" #include "platform_t.h" #include "util.h" target_info_t ir_target; int ir_target_set_triple(ir_machine_triple_t const *machine) { memset(&ir_target, 0, sizeof(ir_target)); ir_target.allow_ifconv = ir_is_optimizable_mux; const char *const cpu = ir_triple_get_cpu_type(machine); const char *const manufacturer = ir_triple_get_manufacturer(machine); char const *arch = NULL; arch_isa_if_t const *isa; if (ir_is_cpu_x86_32(cpu)) { isa = &ia32_isa_if; arch = cpu; } else if (streq(cpu, "arm")) { isa = &arm_isa_if; } else if (streq(cpu, "sparc")) { isa = &sparc_isa_if; if (strstr(manufacturer, "leon") != NULL || streq(manufacturer, "invasic")) arch = "leon"; } else if (streq(cpu, "x86_64") || streq(cpu, "amd64")) { isa = &amd64_isa_if; } else if (streq(cpu, "mips")) { isa = &mips_isa_if; } else if (streq(cpu, "riscv32")) { isa = &riscv32_isa_if; } else if (streq(cpu, "TEMPLATE")) { isa = &TEMPLATE_isa_if; } else { return false; } ir_target.isa = isa; if (arch != NULL) { bool res = be_set_arch(arch); if (!res) panic("Could not set backend arch"); } ir_platform_set(machine, isa->pointer_size); return true; } int ir_target_set(const char *target_triple) { ir_machine_triple_t *target = ir_parse_machine_triple(target_triple); if (target == NULL) return false; int res = ir_target_set_triple(target); ir_free_machine_triple(target); return res; } void ir_target_init(void) { /* Construct mode_P */ arch_isa_if_t const *const isa = ir_target.isa; unsigned const pointer_size = isa->pointer_size; unsigned const modulo_shift = isa->modulo_shift; unsigned const ptr_modulo_shift = modulo_shift == 0 ? 0 : MAX(modulo_shift, pointer_size*8); ir_mode *const ptr_mode = new_reference_mode("P", pointer_size*8, ptr_modulo_shift); set_modeP(ptr_mode); be_initialize(); ir_target.isa->init(); ir_target.isa_initialized = true; ir_platform_init(); } void ir_init(void) { ir_init_library(); ir_machine_triple_t *target = ir_get_host_machine_triple(); ir_target_set_triple(target); ir_free_machine_triple(target); ir_target_init(); } void finish_target(void) { ir_platform_finish(); } int ir_target_option(const char *arg) { assert(ir_target.isa != NULL && "Did not call ir_target_set yet"); lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be"); if (streq(arg, "help") || streq(arg, "?")) { lc_opt_print_help_for_entry(be_grp, '-', stdout); return -1; } /* backend args may not have an effect anymore after the backend * has been initialized */ assert(!ir_target.isa_initialized && "Target already initiazed"); int res = lc_opt_from_single_arg(be_grp, arg); if (res) return res; /* Try passing the option along to the target */ lc_opt_entry_t *target_grp = lc_opt_get_grp(be_grp, ir_target.isa->name); return lc_opt_from_single_arg(target_grp, arg); } int (ir_target_big_endian)(void) { return ir_target_big_endian_(); } unsigned ir_target_biggest_alignment(void) { return 1u << ir_target.isa->po2_biggest_alignment; } unsigned ir_target_pointer_size(void) { return ir_target.isa->pointer_size; } int ir_target_fast_unaligned_memaccess(void) { assert(ir_target.isa_initialized); return ir_target.fast_unaligned_memaccess; } int ir_target_supports_pic(void) { return ir_target.isa->pic_supported; } char const *ir_target_experimental(void) { assert(ir_target.isa_initialized); return ir_target.experimental; } ir_mode *ir_target_float_arithmetic_mode(void) { assert(ir_target.isa_initialized); return ir_target.mode_float_arithmetic; } float_int_conversion_overflow_style_t ir_target_float_int_overflow_style(void) { assert(ir_target.isa_initialized); return ir_target.float_int_overflow; }