* @file
* @brief This file implements the ia32 node emitter.
* @author Christian Wuerdig, Matthias Braun
- * @version $Id$
*
* Summary table for x86 floatingpoint compares:
* (remember effect of unordered on x86: ZF=1, PF=1, CF=1)
#include "raw_bitset.h"
#include "dbginfo.h"
#include "lc_opts.h"
+#include "ircons.h"
#include "besched.h"
#include "benode.h"
#include "beabi.h"
-#include "be_dbgout.h"
+#include "bedwarf.h"
#include "beemitter.h"
#include "begnuas.h"
#include "beirg.h"
-#include "be_dbgout.h"
#include "ia32_emitter.h"
#include "ia32_common_transform.h"
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
-#define SNPRINTF_BUF_LEN 128
-
static const ia32_isa_t *isa;
static char pic_base_label[128];
static ir_label_t exc_label_id;
static int mark_spill_reload = 0;
static int do_pic;
+static bool sp_relative;
+static int frame_type_size;
+static int callframe_offset;
+
/** Return the next block in Block schedule */
static ir_node *get_prev_block_sched(const ir_node *block)
{
int need_label = 1;
int n_cfgpreds = get_Block_n_cfgpreds(block);
- if (has_Block_entity(block))
+ if (get_Block_entity(block) != NULL)
return 1;
if (n_cfgpreds == 0) {
be_gas_emit_entity(entity);
if (get_entity_owner(entity) == get_tls_type()) {
- if (get_entity_visibility(entity) == ir_visibility_external) {
+ if (!entity_has_definition(entity)) {
be_emit_cstring("@INDNTPOFF");
} else {
be_emit_cstring("@NTPOFF");
*/
static void emit_ia32_SwitchJmp(const ir_node *node)
{
- ir_entity *jump_table = get_ia32_am_sc(node);
- long default_pn = get_ia32_default_pn(node);
+ ir_entity *jump_table = get_ia32_am_sc(node);
+ const ir_switch_table *table = get_ia32_switch_table(node);
ia32_emitf(node, "\tjmp %*AM\n");
- emit_jump_table(node, default_pn, jump_table, get_cfop_target_block);
+ be_emit_jump_table(node, table, jump_table, get_cfop_target_block);
}
/**
panic("Invalid asm op modifier");
}
} else {
- emit_register(reg, asm_reg->mode);
+ emit_register(reg, asm_reg->memory ? mode_Iu : asm_reg->mode);
}
if (asm_reg->memory) {
#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();
if (op->ops.generic) {
emit_func_ptr func = (emit_func_ptr) op->ops.generic;
- be_dbg_set_dbg_info(get_irn_dbg_info(node));
+ be_dwarf_location(get_irn_dbg_info(node));
(*func) (node);
} else {
ir_fprintf(stderr, "Error: No emit handler for node %+F (%+G, graph %+F)\n", node, node, current_ir_graph);
abort();
}
+
+ if (sp_relative) {
+ int sp_change = arch_get_sp_bias(node);
+ if (sp_change != 0) {
+ assert(sp_change != SP_BIAS_RESET);
+ callframe_offset += sp_change;
+ be_dwarf_callframe_offset(callframe_offset);
+ }
+ }
}
/**
ia32_emit_block_header(block);
+ if (sp_relative) {
+ ir_graph *irg = get_irn_irg(block);
+ callframe_offset = 4; /* 4 bytes for the return address */
+ /* ESP guessing, TODO perform a real ESP simulation */
+ if (block != get_irg_start_block(irg)) {
+ callframe_offset += frame_type_size;
+ }
+ be_dwarf_callframe_offset(callframe_offset);
+ }
+
/* emit the contents of the block */
- be_dbg_set_dbg_info(get_irn_dbg_info(block));
+ be_dwarf_location(get_irn_dbg_info(block));
sched_foreach(block, node) {
ia32_emit_node(node);
}
return +1;
}
+static parameter_dbg_info_t *construct_parameter_infos(ir_graph *irg)
+{
+ ir_entity *entity = get_irg_entity(irg);
+ ir_type *type = get_entity_type(entity);
+ size_t n_params = get_method_n_params(type);
+ be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
+ ir_type *arg_type = layout->arg_type;
+ size_t n_members = get_compound_n_members(arg_type);
+ parameter_dbg_info_t *infos = XMALLOCNZ(parameter_dbg_info_t, n_params);
+ size_t i;
+
+ for (i = 0; i < n_members; ++i) {
+ ir_entity *member = get_compound_member(arg_type, i);
+ size_t param;
+ if (!is_parameter_entity(member))
+ continue;
+ param = get_entity_parameter_number(member);
+ if (param == IR_VA_START_PARAMETER_NUMBER)
+ continue;
+ assert(infos[param].entity == NULL && infos[param].reg == NULL);
+ infos[param].reg = NULL;
+ infos[param].entity = member;
+ }
+
+ return infos;
+}
+
/**
* Main driver. Emits the code for one routine.
*/
const arch_env_t *arch_env = be_get_irg_arch_env(irg);
ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
ir_node **blk_sched = irg_data->blk_sched;
+ be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
+ parameter_dbg_info_t *infos;
int i, n;
isa = (ia32_isa_t*) arch_env;
get_unique_label(pic_base_label, sizeof(pic_base_label), "PIC_BASE");
- be_dbg_method_begin(entity);
- be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment);
+ infos = construct_parameter_infos(irg);
+ be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment,
+ infos);
+ xfree(infos);
+
+ sp_relative = layout->sp_relative;
+ if (layout->sp_relative) {
+ ir_type *frame_type = get_irg_frame_type(irg);
+ frame_type_size = get_type_size_bytes(frame_type);
+ be_dwarf_callframe_register(&ia32_registers[REG_ESP]);
+ } else {
+ /* well not entirely correct here, we should emit this after the
+ * "movl esp, ebp" */
+ be_dwarf_callframe_register(&ia32_registers[REG_EBP]);
+ /* TODO: do not hardcode the following */
+ be_dwarf_callframe_offset(8);
+ be_dwarf_callframe_spilloffset(&ia32_registers[REG_EBP], -8);
+ }
/* we use links to point to target blocks */
ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
}
be_gas_emit_function_epilog(entity);
- be_dbg_method_end();
- be_emit_char('\n');
- be_emit_write_line();
ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
be_gas_emit_entity(entity);
if (get_entity_owner(entity) == get_tls_type()) {
- if (get_entity_visibility(entity) == ir_visibility_external) {
+ if (!entity_has_definition(entity)) {
be_emit_cstring("@INDNTPOFF");
} else {
be_emit_cstring("@NTPOFF");
static void bemit_switchjmp(const ir_node *node)
{
- ir_entity *jump_table = get_ia32_am_sc(node);
- long default_pn = get_ia32_default_pn(node);
+ ir_entity *jump_table = get_ia32_am_sc(node);
+ const ir_switch_table *table = get_ia32_switch_table(node);
bemit8(0xFF); // jmp *tbl.label(,%in,4)
bemit_mod_am(0x05, node);
- emit_jump_table(node, default_pn, jump_table, get_cfop_target_block);
+ be_emit_jump_table(node, table, jump_table, get_cfop_target_block);
}
/**
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);
ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
ir_node **blk_sched = irg_data->blk_sched;
size_t i, n;
+ parameter_dbg_info_t *infos;
isa = (ia32_isa_t*) arch_env;
ia32_register_binary_emitters();
- be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment);
+ infos = construct_parameter_infos(irg);
+ be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment,
+ NULL);
+ xfree(infos);
/* we use links to point to target blocks */
ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
}
be_gas_emit_function_epilog(entity);
- be_dbg_method_end();
- be_emit_char('\n');
- be_emit_write_line();
ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
}