Commit 6bb28287 authored by Matthias Braun's avatar Matthias Braun
Browse files

make opcode list global

The opcode list was a member of irprog before which wasn't really
handled consistently. Also make sure opcodes are properly freed at
ir_finish().
parent dc0ab1c4
......@@ -283,6 +283,20 @@ FIRM_API ir_op *new_ir_op(unsigned code, const char *name, op_pin_state p,
unsigned flags, op_arity opar, int op_index,
size_t attr_size, const ir_op_ops *ops);
/** Returns one more than the highest opcode code in use. */
FIRM_API unsigned ir_get_n_opcodes(void);
/**
* Returns the opcode with code @p code.
*
* @p code has to be smaller than get_irp_n_opcode(), returns NULL if
* no opcode with the code exists.
*/
FIRM_API ir_op *ir_get_opcode(unsigned code);
/** Sets the generic function pointer of all opcodes to NULL */
FIRM_API void ir_clear_opcodes_generic_func(void);
/**
* Sets memory input of operation using memory
*/
......
......@@ -236,22 +236,6 @@ FIRM_API size_t get_irp_n_modes(void);
/** Returns the mode at position pos in the irp. */
FIRM_API ir_mode *get_irp_mode(size_t pos);
/** Adds opcode to the list of opcodes in irp. */
FIRM_API void add_irp_opcode(ir_op *opcode);
/** Removes opcode from the list of opcodes, deallocates it and
shrinks the list by one. */
FIRM_API void remove_irp_opcode(ir_op *opcode);
/** Returns the number of all opcodes in the irp. */
FIRM_API size_t get_irp_n_opcodes(void);
/** Returns the opcode at position pos in the irp. */
FIRM_API ir_op *get_irp_opcode(size_t pos);
/** Sets the generic function pointer of all opcodes to NULL */
FIRM_API void clear_irp_opcodes_generic_func(void);
/** Returns the graph for global constants of the current irp.
*
* Returns an irgraph that only contains constant expressions for
......
......@@ -175,7 +175,7 @@ static inline void set_emitter(ir_op *op, emit_func func)
static void TEMPLATE_register_emitters(void)
{
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
/* register all emitter functions defined in spec */
TEMPLATE_register_spec_emitters();
......
......@@ -154,6 +154,11 @@ static void TEMPLATE_init(void)
TEMPLATE_create_opcodes(&TEMPLATE_irn_ops);
}
static void TEMPLATE_finish(void)
{
TEMPLATE_free_opcodes();
}
static arch_env_t *TEMPLATE_begin_codegeneration(const be_main_env_t *env)
{
TEMPLATE_isa_t *isa = XMALLOC(TEMPLATE_isa_t);
......@@ -356,6 +361,7 @@ static int TEMPLATE_register_saved_by(const arch_register_t *reg, int callee)
const arch_isa_if_t TEMPLATE_isa_if = {
TEMPLATE_init,
TEMPLATE_finish,
TEMPLATE_get_backend_params,
TEMPLATE_lower_for_target,
TEMPLATE_parse_asm_constraint,
......
......@@ -486,7 +486,7 @@ static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
static void amd64_register_emitters(void)
{
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
/* register all emitter functions defined in spec */
amd64_register_spec_emitters();
......
......@@ -301,6 +301,11 @@ static void amd64_init(void)
amd64_create_opcodes(&amd64_irn_ops);
}
static void amd64_finish(void)
{
amd64_free_opcodes();
}
static arch_env_t *amd64_begin_codegeneration(const be_main_env_t *env)
{
amd64_isa_t *isa = XMALLOC(amd64_isa_t);
......@@ -536,6 +541,7 @@ static int amd64_register_saved_by(const arch_register_t *reg, int callee)
const arch_isa_if_t amd64_isa_if = {
amd64_init,
amd64_finish,
amd64_get_backend_params,
amd64_lower_for_target,
amd64_parse_asm_constraint,
......
......@@ -794,7 +794,7 @@ static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
static void arm_register_emitters(void)
{
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
/* register all emitter functions defined in spec */
arm_register_spec_emitters();
......
......@@ -267,7 +267,7 @@ static void register_peephole_optimisation(ir_op *op, peephole_opt_func func)
void arm_peephole_optimization(ir_graph *irg)
{
/* register peephole optimizations */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
register_peephole_optimisation(op_arm_Str, peephole_arm_Str_Ldr);
register_peephole_optimisation(op_arm_Ldr, peephole_arm_Str_Ldr);
......
......@@ -433,6 +433,11 @@ static void arm_init(void)
arm_create_opcodes(&arm_irn_ops);
}
static void arm_finish(void)
{
arm_free_opcodes();
}
static arch_env_t *arm_begin_codegeneration(const be_main_env_t *env)
{
arm_isa_t *isa = XMALLOC(arm_isa_t);
......@@ -564,6 +569,7 @@ static const lc_opt_table_entry_t arm_options[] = {
const arch_isa_if_t arm_isa_if = {
arm_init,
arm_finish,
arm_get_libfirm_params,
arm_lower_for_target,
arm_parse_asm_constraint,
......
......@@ -437,6 +437,11 @@ struct arch_isa_if_t {
*/
void (*init)(void);
/**
* Fress resources allocated by this isa interface.
*/
void (*finish)(void);
/**
* Returns the frontend settings needed for this backend.
*/
......@@ -547,7 +552,7 @@ struct arch_isa_if_t {
* Called directly before done is called. This should be the last place
* where the irg is modified.
*/
void (*finish)(ir_graph *irg);
void (*finish_graph)(ir_graph *irg);
/**
* Called after everything happened. This call should emit the final
......
......@@ -151,6 +151,15 @@ static void initialize_isa(void)
if (isa_initialized)
return;
isa_if->init();
isa_initialized = true;
}
static void finish_isa(void)
{
if (isa_initialized) {
isa_if->finish();
isa_initialized = false;
}
}
void be_init_default_asm_constraint_flags(void)
......@@ -341,6 +350,7 @@ void firm_be_init(void)
/* Finalize the Firm backend. */
void firm_be_finish(void)
{
finish_isa();
be_quit_modules();
}
......@@ -720,8 +730,8 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
dump(DUMP_RA, irg, "ra");
be_timer_push(T_FINISH);
if (arch_env->impl->finish != NULL)
arch_env->impl->finish(irg);
if (arch_env->impl->finish_graph != NULL)
arch_env->impl->finish_graph(irg);
be_timer_pop(T_FINISH);
dump(DUMP_FINAL, irg, "finish");
......
......@@ -1334,6 +1334,8 @@ void be_init_op(void)
{
unsigned opc;
assert(op_be_Spill == NULL);
/* Acquire all needed opcodes. */
op_be_Spill = new_ir_op(beo_Spill, "be_Spill", op_pin_state_exc_pinned, irop_flag_none, oparity_unary, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
op_be_Reload = new_ir_op(beo_Reload, "be_Reload", op_pin_state_exc_pinned, irop_flag_none, oparity_zero, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
......@@ -1369,10 +1371,28 @@ void be_init_op(void)
/* attach out dummy_ops to middle end nodes */
for (opc = iro_First; opc <= iro_Last; ++opc) {
ir_op *op = get_irp_opcode(opc);
ir_op *op = ir_get_opcode(opc);
assert(op->ops.be_ops == NULL);
op->ops.be_ops = &dummy_be_irn_ops;
}
op_Phi->ops.be_ops = &phi_irn_ops;
}
void be_finish_op(void)
{
free_ir_op(op_be_Spill); op_be_Spill = NULL;
free_ir_op(op_be_Reload); op_be_Reload = NULL;
free_ir_op(op_be_Perm); op_be_Perm = NULL;
free_ir_op(op_be_MemPerm); op_be_MemPerm = NULL;
free_ir_op(op_be_Copy); op_be_Copy = NULL;
free_ir_op(op_be_Keep); op_be_Keep = NULL;
free_ir_op(op_be_CopyKeep); op_be_CopyKeep = NULL;
free_ir_op(op_be_Call); op_be_Call = NULL;
free_ir_op(op_be_Return); op_be_Return = NULL;
free_ir_op(op_be_IncSP); op_be_IncSP = NULL;
free_ir_op(op_be_AddSP); op_be_AddSP = NULL;
free_ir_op(op_be_SubSP); op_be_SubSP = NULL;
free_ir_op(op_be_Start); op_be_Start = NULL;
free_ir_op(op_be_FrameAddr); op_be_FrameAddr = NULL;
}
......@@ -63,6 +63,8 @@ int is_be_node(const ir_node *irn);
*/
void be_init_op(void);
void be_finish_op(void);
/**
* Position numbers for the be_Spill inputs.
*/
......
......@@ -149,7 +149,7 @@ static ir_node *transform_end(ir_node *node)
void be_start_transform_setup(void)
{
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
be_set_transform_function(op_Bad, be_duplicate_node);
be_set_transform_function(op_be_Copy, be_duplicate_node);
......
......@@ -1310,7 +1310,7 @@ static void introduce_prolog_epilog(ir_graph *irg)
* virtual with real x87 instructions, creating a block schedule and peephole
* optimisations.
*/
static void ia32_finish(ir_graph *irg)
static void ia32_finish_graph(ir_graph *irg)
{
ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
......@@ -1736,9 +1736,6 @@ static void ia32_init(void)
init_asm_constraints();
ia32_register_init();
ia32_create_opcodes(&ia32_irn_ops);
ia32_mode_fpcw = new_int_mode("Fpcw", irma_twos_complement, 16, 0, 0);
/* note mantissa is 64bit but with explicitely encoded 1 so the really
......@@ -1764,6 +1761,14 @@ static void ia32_init(void)
ia32_backend_params.mode_float_arithmetic = ia32_mode_E;
ia32_backend_params.type_long_double = ia32_type_E;
}
ia32_register_init();
ia32_create_opcodes(&ia32_irn_ops);
}
static void ia32_finish(void)
{
ia32_free_opcodes();
}
/**
......@@ -2042,8 +2047,6 @@ static void ia32_lower_for_target(void)
&intrinsic_env,
};
ia32_create_opcodes(&ia32_irn_ops);
/* lower compound param handling
* Note: we lower compound arguments ourself, since on ia32 we don't
* have hidden parameters but know where to find the structs on the stack.
......@@ -2163,6 +2166,7 @@ static const lc_opt_table_entry_t ia32_options[] = {
const arch_isa_if_t ia32_isa_if = {
ia32_init,
ia32_finish,
ia32_get_libfirm_params,
ia32_lower_for_target,
ia32_parse_asm_constraint,
......@@ -2182,7 +2186,7 @@ const arch_isa_if_t ia32_isa_if = {
ia32_before_abi, /* before abi introduce hook */
ia32_prepare_graph,
ia32_before_ra, /* before register allocation hook */
ia32_finish, /* called before codegen */
ia32_finish_graph, /* called before codegen */
ia32_emit, /* emit && done */
};
......
......@@ -1560,7 +1560,7 @@ static void ia32_register_emitters(void)
#define BE_IGN(a) op_be_##a->ops.generic = (op_func)emit_Nothing
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
/* register all emitter functions defined in spec */
ia32_register_spec_emitters();
......@@ -3668,7 +3668,7 @@ static void register_emitter(ir_op *op, emit_func func)
static void ia32_register_binary_emitters(void)
{
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
/* benode emitter */
register_emitter(op_be_Copy, bemit_copy);
......
......@@ -1278,7 +1278,7 @@ void ia32_peephole_optimization(ir_graph *irg)
*/
/* pass 1 */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
register_peephole_optimisation(op_ia32_Cmp, peephole_ia32_Cmp);
register_peephole_optimisation(op_ia32_Cmp8Bit, peephole_ia32_Cmp);
register_peephole_optimisation(op_ia32_Lea, peephole_ia32_Lea);
......@@ -1291,7 +1291,7 @@ void ia32_peephole_optimization(ir_graph *irg)
be_peephole_opt(irg);
/* pass 2 */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
register_peephole_optimisation(op_ia32_Const, peephole_ia32_Const);
register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
register_peephole_optimisation(op_ia32_Test, peephole_ia32_Test);
......
......@@ -2208,7 +2208,7 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg)
"x87 Simulator started for %+F\n", irg));
/* set the generic function pointer of instruction we must simulate */
clear_irp_opcodes_generic_func();
ir_clear_opcodes_generic_func();
register_sim(op_ia32_Call, sim_Call);
register_sim(op_ia32_vfld, sim_fld);
......
......@@ -116,6 +116,7 @@ my @obst_opvar; # stack for the "ir_op *op_<arch>_<op-name> = NULL;" state
my @obst_get_opvar; # stack for the get_op_<arch>_<op-name>() functions
my $obst_constructor; # stack for node constructor functions
my @obst_new_irop; # stack for the new_ir_op calls
my @obst_free_irop; # stack for free_ir_op calls
my @obst_enum_op; # stack for creating the <arch>_opcode enum
my $obst_header; # stack for function prototypes
my @obst_is_archirn; # stack for the is_$arch_irn() function
......@@ -159,6 +160,7 @@ foreach my $class_name (keys(%reg_classes)) {
$n_opcodes += $additional_opcodes if (defined($additional_opcodes));
$obst_header .= "void ${arch}_create_opcodes(const arch_irn_ops_t *be_ops);\n";
$obst_header .= "void ${arch}_free_opcodes(void);\n";
sub create_constructor {
my $op = shift;
......@@ -712,6 +714,8 @@ EOF
push(@obst_new_irop, "\tset_op_attr(op_$op, attr);\n");
}
push(@obst_free_irop, "\tfree_ir_op(op_$op); op_$op = NULL;\n");
push(@obst_enum_op, "\tiro_$op,\n");
$obst_header .= "\n";
......@@ -817,10 +821,10 @@ $obst_constructor
* Creates the $arch specific Firm machine operations
* needed for the assembler irgs.
*/
void $arch\_create_opcodes(const arch_irn_ops_t *be_ops) {
void $arch\_create_opcodes(const arch_irn_ops_t *be_ops)
{
ir_op_ops ops;
int cur_opcode;
static int run_once = 0;
ENDOFMAIN
if (defined($default_op_attr_type)) {
......@@ -829,10 +833,6 @@ ENDOFMAIN
print OUT<<ENDOFMAIN;
if (run_once)
return;
run_once = 1;
cur_opcode = get_next_ir_opcodes(iro_$arch\_last);
$arch\_opcode_start = cur_opcode;
......@@ -848,7 +848,18 @@ print OUT "\t$arch\_register_additional_opcodes(cur_opcode);\n" if (defined($add
print OUT "\t$arch\_opcode_end = cur_opcode + iro_$arch\_last";
print OUT " + $additional_opcodes" if (defined($additional_opcodes));
print OUT ";\n";
print OUT "}\n";
print OUT <<ENDOFMAIN;
}
void $arch\_free_opcodes(void)
{
ENDOFMAIN
print OUT @obst_free_irop;
print OUT <<ENDOFMAIN;
}
ENDOFMAIN
close(OUT);
......
......@@ -347,6 +347,11 @@ static void sparc_init(void)
sparc_cconv_init();
}
static void sparc_finish(void)
{
sparc_free_opcodes();
}
static arch_env_t *sparc_begin_codegeneration(const be_main_env_t *env)
{
sparc_isa_t *isa = XMALLOC(sparc_isa_t);
......@@ -541,6 +546,7 @@ static ir_node *sparc_new_reload(ir_node *value, ir_node *spill,
const arch_isa_if_t sparc_isa_if = {
sparc_init,
sparc_finish,
sparc_get_backend_params,
sparc_lower_for_target,
sparc_parse_asm_constraint,
......@@ -560,7 +566,7 @@ const arch_isa_if_t sparc_isa_if = {
NULL, /* before_abi */
sparc_prepare_graph,
sparc_before_ra,
sparc_finish,
sparc_finish_graph,
sparc_emit_routine,
};
......
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