Commit 5609f2c7 authored by Matthias Braun's avatar Matthias Braun
Browse files

be: rework isa_if interface and initialisation

This should fix problems with uninitialized backends when
be_get_backend_param() wasn't called also calls be_lower_for_target if
the user hasn't done so yet.
parent c6f280da
......@@ -148,16 +148,16 @@ static TEMPLATE_isa_t TEMPLATE_isa_template = {
},
};
/**
* Initializes the backend ISA
*/
static arch_env_t *TEMPLATE_init(const be_main_env_t *env)
static void TEMPLATE_init(void)
{
TEMPLATE_isa_t *isa = XMALLOC(TEMPLATE_isa_t);
*isa = TEMPLATE_isa_template;
TEMPLATE_register_init();
TEMPLATE_create_opcodes(&TEMPLATE_irn_ops);
}
static arch_env_t *TEMPLATE_begin_codegeneration(const be_main_env_t *env)
{
TEMPLATE_isa_t *isa = XMALLOC(TEMPLATE_isa_t);
*isa = TEMPLATE_isa_template;
be_emit_init(env->file_handle);
be_gas_begin_compilation_unit(env);
......@@ -168,7 +168,7 @@ static arch_env_t *TEMPLATE_init(const be_main_env_t *env)
/**
* Closes the output file and frees the ISA structure.
*/
static void TEMPLATE_done(void *self)
static void TEMPLATE_end_codegeneration(void *self)
{
TEMPLATE_isa_t *isa = (TEMPLATE_isa_t*)self;
......@@ -356,25 +356,27 @@ static int TEMPLATE_register_saved_by(const arch_register_t *reg, int callee)
const arch_isa_if_t TEMPLATE_isa_if = {
TEMPLATE_init,
TEMPLATE_lower_for_target,
TEMPLATE_done,
NULL, /* handle intrinsics */
TEMPLATE_get_call_abi,
TEMPLATE_get_backend_params,
NULL, /* mark remat */
TEMPLATE_lower_for_target,
TEMPLATE_parse_asm_constraint,
TEMPLATE_is_valid_clobber,
TEMPLATE_begin_codegeneration,
TEMPLATE_end_codegeneration,
TEMPLATE_init_graph,
NULL, /* get_pic_base */
NULL, /* before_abi */
TEMPLATE_get_call_abi,
NULL, /* mark remat */
NULL, /* get_pic_base */
be_new_spill,
be_new_reload,
TEMPLATE_register_saved_by,
NULL, /* handle intrinsics */
NULL, /* before_abi */
TEMPLATE_prepare_graph,
TEMPLATE_before_ra,
TEMPLATE_finish_irg,
TEMPLATE_emit_routine,
TEMPLATE_register_saved_by,
be_new_spill,
be_new_reload,
};
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE)
......
......@@ -295,16 +295,16 @@ static amd64_isa_t amd64_isa_template = {
},
};
/**
* Initializes the backend ISA
*/
static arch_env_t *amd64_init(const be_main_env_t *env)
static void amd64_init(void)
{
amd64_isa_t *isa = XMALLOC(amd64_isa_t);
*isa = amd64_isa_template;
amd64_register_init();
amd64_create_opcodes(&amd64_irn_ops);
}
static arch_env_t *amd64_begin_codegeneration(const be_main_env_t *env)
{
amd64_isa_t *isa = XMALLOC(amd64_isa_t);
*isa = amd64_isa_template;
be_emit_init(env->file_handle);
be_gas_begin_compilation_unit(env);
......@@ -312,12 +312,10 @@ static arch_env_t *amd64_init(const be_main_env_t *env)
return &isa->base;
}
/**
* Closes the output file and frees the ISA structure.
*/
static void amd64_done(void *self)
static void amd64_end_codegeneration(void *self)
{
amd64_isa_t *isa = (amd64_isa_t*)self;
......@@ -538,25 +536,27 @@ static int amd64_register_saved_by(const arch_register_t *reg, int callee)
const arch_isa_if_t amd64_isa_if = {
amd64_init,
amd64_lower_for_target,
amd64_done,
NULL, /* handle intrinsics */
amd64_get_call_abi,
amd64_get_backend_params,
NULL, /* mark remat */
amd64_lower_for_target,
amd64_parse_asm_constraint,
amd64_is_valid_clobber,
amd64_begin_codegeneration,
amd64_end_codegeneration,
amd64_init_graph,
amd64_get_call_abi,
NULL, /* mark remat */
NULL, /* get_pic_base */
be_new_spill,
be_new_reload,
amd64_register_saved_by,
NULL, /* handle intrinsics */
NULL, /* before_abi */
amd64_prepare_graph,
amd64_before_ra,
amd64_finish_irg,
amd64_gen_routine,
amd64_register_saved_by,
be_new_spill,
be_new_reload
};
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_amd64)
......
......@@ -426,18 +426,17 @@ static arm_isa_t arm_isa_template = {
ARM_FPU_ARCH_FPE, /* FPU architecture */
};
/**
* Initializes the backend ISA and opens the output file.
*/
static arch_env_t *arm_init(const be_main_env_t *env)
static void arm_init(void)
{
arm_isa_t *isa = XMALLOC(arm_isa_t);
*isa = arm_isa_template;
arm_register_init();
arm_create_opcodes(&arm_irn_ops);
arm_handle_intrinsics();
}
static arch_env_t *arm_begin_codegeneration(const be_main_env_t *env)
{
arm_isa_t *isa = XMALLOC(arm_isa_t);
*isa = arm_isa_template;
be_gas_emit_types = false;
......@@ -447,12 +446,10 @@ static arch_env_t *arm_init(const be_main_env_t *env)
return &isa->base;
}
/**
* Closes the output file and frees the ISA structure.
*/
static void arm_done(void *self)
static void arm_end_codegeneration(void *self)
{
arm_isa_t *isa = (arm_isa_t*)self;
......@@ -567,25 +564,27 @@ static const lc_opt_table_entry_t arm_options[] = {
const arch_isa_if_t arm_isa_if = {
arm_init,
arm_lower_for_target,
arm_done,
NULL, /* handle_intrinsics */
NULL,
arm_get_libfirm_params,
NULL, /* mark remat */
arm_lower_for_target,
arm_parse_asm_constraint,
arm_is_valid_clobber,
arm_begin_codegeneration,
arm_end_codegeneration,
arm_init_graph,
NULL, /* get call abi */
NULL, /* mark remat */
NULL, /* get_pic_base */
be_new_spill,
be_new_reload,
NULL, /* register_saved_by */
arm_handle_intrinsics, /* handle_intrinsics */
NULL, /* before_abi */
arm_prepare_graph,
arm_before_ra,
arm_finish_irg,
arm_gen_routine,
NULL, /* register_saved_by */
be_new_spill,
be_new_reload,
};
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm)
......
......@@ -55,9 +55,10 @@ static reg_out_info_t dummy_info = {
};
/* Initialize the architecture environment struct. */
arch_env_t *arch_env_init(const arch_isa_if_t *isa_if, be_main_env_t *main_env)
arch_env_t *arch_env_begin_codegeneration(const arch_isa_if_t *isa_if,
be_main_env_t *main_env)
{
arch_env_t *arch_env = isa_if->init(main_env);
arch_env_t *arch_env = isa_if->begin_codegeneration(main_env);
arch_env->main_env = main_env;
return arch_env;
}
......
......@@ -212,13 +212,10 @@ static inline unsigned arch_get_irn_n_outs(const ir_node *node)
}
/**
* Initialize the architecture environment struct.
* @param isa The isa which shall be put into the environment.
* @param file_handle The file handle
* @return The environment.
* Start codegeneration
*/
extern arch_env_t *arch_env_init(const arch_isa_if_t *isa,
be_main_env_t *main_env);
arch_env_t *arch_env_begin_codegeneration(const arch_isa_if_t *isa,
be_main_env_t *main_env);
/**
* Register an instruction set architecture
......@@ -435,11 +432,15 @@ struct arch_irn_ops_t {
*/
struct arch_isa_if_t {
/**
* Initialize the isa interface.
* @param file_handle the file handle to write the output to
* @return a new isa instance
* Initializes the isa interface. This is necessary before calling any
* other functions from this interface.
*/
void (*init)(void);
/**
* Returns the frontend settings needed for this backend.
*/
arch_env_t *(*init)(const be_main_env_t *env);
const backend_params *(*get_params)(void);
/**
* lowers current program for target. See the documentation for
......@@ -447,16 +448,35 @@ struct arch_isa_if_t {
*/
void (*lower_for_target)(void);
/**
* parse an assembler constraint part and set flags according to its nature
* advances the *c pointer to point to the last parsed character (so if you
* parse a single character don't advance c)
*/
asm_constraint_flags_t (*parse_asm_constraint)(const char **c);
/**
* returns true if the string is a valid clobbered (register) in this
* backend
*/
int (*is_valid_clobber)(const char *clobber);
/**
* Start codegeneration
* @return a new isa instance
*/
arch_env_t *(*begin_codegeneration)(const be_main_env_t *env);
/**
* Free the isa instance.
*/
void (*done)(void *self);
void (*end_codegeneration)(void *self);
/**
* Called directly after initialization. Backend should handle all
* intrinsics here.
* Initialize the code generator for a graph
* @param irg A graph
*/
void (*handle_intrinsics)(void);
void (*init_graph)(ir_graph *irg);
/**
* Get the ABI restrictions for procedure calls.
......@@ -466,40 +486,47 @@ struct arch_isa_if_t {
void (*get_call_abi)(ir_type *call_type, be_abi_call_t *abi);
/**
* A "static" function, returns the frontend settings
* needed for this backend.
* mark node as rematerialized
*/
const backend_params *(*get_params)(void);
void (*mark_remat)(ir_node *node);
/**
* mark node as rematerialized
* return node used as base in pic code addresses
*/
void (*mark_remat)(ir_node *node);
ir_node* (*get_pic_base)(ir_graph *irg);
/**
* parse an assembler constraint part and set flags according to its nature
* advances the *c pointer to point to the last parsed character (so if you
* parse a single character don't advance c)
* Create a spill instruction. We assume that spill instructions
* do not need any additional registers and do not affect cpu-flags in any
* way.
* Construct a sequence of instructions after @p after (the resulting nodes
* are already scheduled).
* Returns a mode_M value which is used as input for a reload instruction.
*/
asm_constraint_flags_t (*parse_asm_constraint)(const char **c);
ir_node *(*new_spill)(ir_node *value, ir_node *after);
/**
* returns true if the string is a valid clobbered (register) in this
* backend
* Create a reload instruction. We assume that reload instructions do not
* need any additional registers and do not affect cpu-flags in any way.
* Constructs a sequence of instruction before @p before (the resulting
* nodes are already scheduled). A rewiring of users is not performed in
* this function.
* Returns a value representing the restored value.
*/
int (*is_valid_clobber)(const char *clobber);
ir_node *(*new_reload)(ir_node *value, ir_node *spilled_value,
ir_node *before);
/**
* Initialize the code generator.
* @param irg A graph
* @return A newly created code generator.
* Checks if the given register is callee/caller saved.
* @deprecated, only necessary if backend still uses beabi functions
*/
void (*init_graph)(ir_graph *irg);
int (*register_saved_by)(const arch_register_t *reg, int callee);
/**
* return node used as base in pic code addresses
* Called directly after initialization. Backend should handle all
* intrinsics here.
*/
ir_node* (*get_pic_base)(ir_graph *irg);
void (*handle_intrinsics)(void);
/**
* Called before abi introduce.
......@@ -525,39 +552,11 @@ struct arch_isa_if_t {
/**
* Called after everything happened. This call should emit the final
* assembly code but avoid changing the irg.
* The code generator must also be de-allocated here.
*/
void (*emit)(ir_graph *irg);
/**
* Checks if the given register is callee/caller saved.
* @deprecated, only necessary if backend still uses beabi functions
*/
int (*register_saved_by)(const arch_register_t *reg, int callee);
/**
* Create a spill instruction. We assume that spill instructions
* do not need any additional registers and do not affect cpu-flags in any
* way.
* Construct a sequence of instructions after @p after (the resulting nodes
* are already scheduled).
* Returns a mode_M value which is used as input for a reload instruction.
*/
ir_node *(*new_spill)(ir_node *value, ir_node *after);
/**
* Create a reload instruction. We assume that reload instructions do not
* need any additional registers and do not affect cpu-flags in any way.
* Constructs a sequence of instruction before @p before (the resulting
* nodes are already scheduled). A rewiring of users is not performed in
* this function.
* Returns a value representing the restored value.
*/
ir_node *(*new_reload)(ir_node *value, ir_node *spilled_value,
ir_node *before);
};
#define arch_env_done(env) ((env)->impl->done(env))
#define arch_env_end_codegeneration(env) ((env)->impl->end_codegeneration(env))
#define arch_env_handle_intrinsics(env) \
do { if((env)->impl->handle_intrinsics != NULL) (env)->impl->handle_intrinsics(); } while(0)
#define arch_env_get_call_abi(env,tp,abi) ((env)->impl->get_call_abi((tp), (abi)))
......
......@@ -140,11 +140,18 @@ static const lc_opt_table_entry_t be_main_options[] = {
LC_OPT_LAST
};
static be_module_list_entry_t *isa_ifs = NULL;
static be_module_list_entry_t *isa_ifs = NULL;
static bool isa_initialized = false;
asm_constraint_flags_t asm_constraint_flags[256];
static void initialize_isa(void)
{
if (isa_initialized)
return;
isa_if->init();
}
void be_init_default_asm_constraint_flags(void)
{
asm_constraint_flags['?'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
......@@ -212,6 +219,8 @@ asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
const char *c;
asm_constraint_flags_t tflags;
initialize_isa();
for (c = constraint; *c != '\0'; ++c) {
switch (*c) {
case '#':
......@@ -261,6 +270,8 @@ asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
int be_is_valid_clobber(const char *clobber)
{
initialize_isa();
/* memory is a valid clobber. (the frontend has to detect this case too,
* because it has to add memory edges to the asm) */
if (strcmp(clobber, "memory") == 0)
......@@ -335,6 +346,7 @@ void firm_be_finish(void)
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
initialize_isa();
return isa_if->get_params();
}
......@@ -361,7 +373,7 @@ static be_main_env_t *be_init_env(be_main_env_t *env, FILE *file_handle,
set_class_final(env->pic_trampolines_type, 1);
memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
env->arch_env = arch_env_init(isa_if, env);
env->arch_env = arch_env_begin_codegeneration(isa_if, env);
return env;
}
......@@ -472,6 +484,11 @@ void be_lower_for_target(void)
{
size_t i;
initialize_isa();
/* shouldn't lower program twice */
assert(get_irp_phase_state() != phase_low);
isa_if->lower_for_target();
/* set the phase to low */
for (i = get_irp_n_irgs(); i > 0;) {
......@@ -501,6 +518,10 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
be_timing = (be_options.timing == BE_TIME_ON);
/* perform target lowering if it didn't happen yet */
if (get_irp_phase_state() != phase_low)
be_lower_for_target();
if (be_timing) {
for (i = 0; i < T_LAST+1; ++i) {
be_timers[i] = ir_timer_new();
......@@ -773,7 +794,7 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
stat_ev_ctx_pop("bemain_irg");
}
arch_env_done(arch_env);
arch_env_end_codegeneration(arch_env);
ir_profile_free();
be_done_env(&env);
......
This diff is collapsed.
......@@ -340,10 +340,14 @@ static void sparc_handle_intrinsics(void)
lower_intrinsics(records, n_records, /*part_block_used=*/ true);
}
/**
* Initializes the backend ISA
*/
static arch_env_t *sparc_init(const be_main_env_t *env)
static void sparc_init(void)
{
sparc_register_init();
sparc_create_opcodes(&sparc_irn_ops);
sparc_cconv_init();
}
static arch_env_t *sparc_begin_codegeneration(const be_main_env_t *env)
{
sparc_isa_t *isa = XMALLOC(sparc_isa_t);
*isa = sparc_isa_template;
......@@ -353,11 +357,6 @@ static arch_env_t *sparc_init(const be_main_env_t *env)
be_gas_object_file_format = OBJECT_FILE_FORMAT_ELF;
be_gas_elf_variant = ELF_VARIANT_SPARC;
sparc_register_init();
sparc_create_opcodes(&sparc_irn_ops);
sparc_handle_intrinsics();
sparc_cconv_init();
be_emit_init(env->file_handle);
be_gas_begin_compilation_unit(env);
......@@ -367,7 +366,7 @@ static arch_env_t *sparc_init(const be_main_env_t *env)
/**
* Closes the output file and frees the ISA structure.
*/
static void sparc_done(void *self)
static void sparc_end_codegeneration(void *self)
{
sparc_isa_t *isa = (sparc_isa_t*)self;
......@@ -542,25 +541,27 @@ static ir_node *sparc_new_reload(ir_node *value, ir_node *spill,
const arch_isa_if_t sparc_isa_if = {
sparc_init,
sparc_lower_for_target,
sparc_done,
NULL, /* handle intrinsics */
NULL,
sparc_get_backend_params,
NULL, /* mark remat */
sparc_lower_for_target,
sparc_parse_asm_constraint,
sparc_is_valid_clobber,
sparc_begin_codegeneration,
sparc_end_codegeneration,
sparc_init_graph,
NULL, /* get_pic_base */
NULL, /* before_abi */
NULL, /* get call abi */
NULL, /* mark remat */
NULL, /* get_pic_base */
sparc_new_spill,
sparc_new_reload,
NULL, /* register_saved_by */
sparc_handle_intrinsics,
NULL, /* before_abi */
sparc_prepare_graph,
sparc_before_ra,
sparc_finish,
sparc_emit_routine,
NULL, /* register_saved_by */
sparc_new_spill,
sparc_new_reload
};
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment