block_schedule = be_create_block_schedule(irg);
/* emit assembler prolog */
- be_gas_emit_function_prolog(entity, 4);
+ be_gas_emit_function_prolog(entity, 4, NULL);
/* populate jump link fields with their destinations */
irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, NULL);
blk_sched = be_create_block_schedule(irg);
- be_gas_emit_function_prolog(entity, 4);
+ be_gas_emit_function_prolog(entity, 4, NULL);
irg_block_walk_graph(irg, amd64_gen_labels, NULL, NULL);
/* create the block schedule */
blk_sched = be_create_block_schedule(irg);
- be_gas_emit_function_prolog(entity, 4);
+ be_gas_emit_function_prolog(entity, 4, NULL);
irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
layout->frame_type = get_irg_frame_type(irg);
layout->between_type = arm_get_between_type();
layout->arg_type = arg_type;
- layout->param_map = NULL; /* TODO */
layout->initial_offset = 0;
layout->initial_bias = 0;
layout->sp_relative = true;
* @param args the stack argument layout type
* @param between the between layout type
* @param locals the method frame type
- * @param param_map an array mapping method argument positions to the stack argument type
*
* @return the initialized stack layout
*/
static be_stack_layout_t *stack_frame_init(be_stack_layout_t *frame, ir_type *args,
- ir_type *between, ir_type *locals,
- ir_entity *param_map[])
+ ir_type *between, ir_type *locals)
{
frame->arg_type = args;
frame->between_type = between;
frame->initial_offset = 0;
frame->initial_bias = 0;
frame->order[1] = between;
- frame->param_map = param_map;
/* typical decreasing stack: locals have the
* lowest addresses, arguments the highest */
*
* @param call the current call ABI
* @param method_type the method type
- * @param param_map an array mapping method arguments to the stack layout
- * type
*
* @return the stack argument layout type
*/
static ir_type *compute_arg_type(ir_graph *irg, be_abi_call_t *call,
- ir_type *method_type, ir_entity ***param_map)
+ ir_type *method_type)
{
struct obstack *obst = be_get_be_obst(irg);
ir_type *frame_type = get_irg_frame_type(irg);
ir_type *res;
size_t i;
- ir_entity **map;
-
- *param_map = map = OALLOCNZ(obst, ir_entity*, n_params);
+ ir_entity **map = OALLOCNZ(obst, ir_entity*, n_params);
res = new_type_struct(new_id_from_chars("arg_type", 8));
/* collect existing entities for value_param_types */
const ir_edge_t *edge;
ir_type *arg_type, *bet_type;
lower_frame_sels_env_t ctx;
- ir_entity **param_map;
DBG((dbg, LEVEL_1, "introducing abi on %+F\n", irg));
irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK);
- arg_type = compute_arg_type(irg, call, method_type, ¶m_map);
+ arg_type = compute_arg_type(irg, call, method_type);
/* Convert the Sel nodes in the irg to frame addr nodes: */
ctx.frame = get_irg_frame(irg);
stack_layout->sp_relative = call->flags.bits.try_omit_fp;
bet_type = call->cb->get_between_type(irg);
stack_frame_init(stack_layout, arg_type, bet_type,
- get_irg_frame_type(irg), param_map);
+ get_irg_frame_type(irg));
/* Count the register params and add them to the number of Projs for the RegParams node */
for (i = 0; i < n_params; ++i) {
typedef enum custom_abbrevs {
abbrev_void_pointer_type = 100,
abbrev_unnamed_formal_parameter,
+ abbrev_formal_parameter_no_location,
abbrev_void_subroutine_type,
+ abbrev_void_subprogram,
abbrev_bitfield_member,
} custom_abbrevs;
*/
typedef struct dwarf_t {
const ir_entity *cur_ent; /**< current method entity */
- const be_stack_layout_t *layout; /**< current stack layout */
unsigned next_type_nr; /**< next type number */
pmap *file_map; /**< a map from file names to number in file list */
const char **file_list;
ARR_APP1(const char*, env.file_list, filename);
num = (unsigned)ARR_LEN(env.file_list);
pmap_insert(env.file_map, filename, INT_TO_PTR(num));
+
/* TODO: quote chars in string */
be_emit_irprintf("\t.file %u \"%s\"\n", num, filename);
return num;
return size;
}
+static void emit_sleb128(long value)
+{
+ be_emit_irprintf("\t.sleb128 %ld\n", value);
+ be_emit_write_line();
+}
+
+static unsigned get_sleb128_size(long value)
+{
+ unsigned size = 0;
+ do {
+ value >>= 7;
+ size += 1;
+ } while (value != 0 && value != -1);
+ return size;
+}
+
static void emit_string(const char *string)
{
+ /* TODO: quote special chars */
be_emit_irprintf("\t.asciz \"%s\"\n", string);
be_emit_write_line();
}
be_emit_write_line();
}
+void be_dwarf_callframe_register(const arch_register_t *reg)
+{
+ if (debug_level < LEVEL_FRAMEINFO)
+ return;
+ be_emit_cstring("\t.cfi_def_cfa_register ");
+ be_emit_irprintf("%d\n", reg->dwarf_number);
+ be_emit_write_line();
+}
+
+void be_dwarf_callframe_offset(int offset)
+{
+ if (debug_level < LEVEL_FRAMEINFO)
+ return;
+ be_emit_cstring("\t.cfi_def_cfa_offset ");
+ be_emit_irprintf("%d\n", offset);
+ be_emit_write_line();
+}
+
+void be_dwarf_callframe_spilloffset(const arch_register_t *reg, int offset)
+{
+ if (debug_level < LEVEL_FRAMEINFO)
+ return;
+ be_emit_cstring("\t.cfi_offset ");
+ be_emit_irprintf("%d, %d\n", reg->dwarf_number, offset);
+ be_emit_write_line();
+}
+
static bool is_extern_entity(const ir_entity *entity)
{
ir_visited_t visibility = get_entity_visibility(entity);
emit_uleb128(loc.column);
}
+static void emit_type_address(const ir_type *type)
+{
+ be_emit_irprintf("\t.long %sT%ld - %sinfo_begin\n",
+ be_gas_get_private_prefix(),
+ get_type_nr(type), be_gas_get_private_prefix());
+ be_emit_write_line();
+}
+
static void emit_subprogram_abbrev(void)
{
- begin_abbrev(DW_TAG_subprogram, DW_TAG_subprogram, DW_CHILDREN_no);
+ begin_abbrev(DW_TAG_subprogram, DW_TAG_subprogram, DW_CHILDREN_yes);
register_attribute(DW_AT_name, DW_FORM_string);
register_dbginfo_attributes();
+ register_attribute(DW_AT_type, DW_FORM_ref4);
+ register_attribute(DW_AT_external, DW_FORM_flag);
+ register_attribute(DW_AT_low_pc, DW_FORM_addr);
+ register_attribute(DW_AT_high_pc, DW_FORM_addr);
//register_attribute(DW_AT_prototyped, DW_FORM_flag);
- //register_attribute(DW_AT_type, DW_FORM_ref4);
- register_attribute(DW_AT_external, DW_FORM_flag);
- register_attribute(DW_AT_low_pc, DW_FORM_addr);
- register_attribute(DW_AT_high_pc, DW_FORM_addr);
- //register_attribute(DW_AT_frame_base, DW_FORM_block1);
+ if (debug_level >= LEVEL_FRAMEINFO)
+ register_attribute(DW_AT_frame_base, DW_FORM_block1);
end_abbrev();
+
+ begin_abbrev(abbrev_void_subprogram, DW_TAG_subprogram, DW_CHILDREN_yes);
+ register_attribute(DW_AT_name, DW_FORM_string);
+ register_dbginfo_attributes();
+ register_attribute(DW_AT_external, DW_FORM_flag);
+ register_attribute(DW_AT_low_pc, DW_FORM_addr);
+ register_attribute(DW_AT_high_pc, DW_FORM_addr);
+ //register_attribute(DW_AT_prototyped, DW_FORM_flag);
+ if (debug_level >= LEVEL_FRAMEINFO)
+ register_attribute(DW_AT_frame_base, DW_FORM_block1);
+ end_abbrev();
+
+ begin_abbrev(DW_TAG_formal_parameter, DW_TAG_formal_parameter,
+ DW_CHILDREN_no);
+ register_attribute(DW_AT_name, DW_FORM_string);
+ register_dbginfo_attributes();
+ register_attribute(DW_AT_type, DW_FORM_ref4);
+ register_attribute(DW_AT_location, DW_FORM_block1);
+ end_abbrev();
+
+ begin_abbrev(abbrev_formal_parameter_no_location, DW_TAG_formal_parameter,
+ DW_CHILDREN_no);
+ register_attribute(DW_AT_name, DW_FORM_string);
+ register_dbginfo_attributes();
+ register_attribute(DW_AT_type, DW_FORM_ref4);
+ end_abbrev();
+}
+
+static void emit_type(ir_type *type);
+
+static void emit_stack_location(long offset)
+{
+ unsigned size = 1 + get_sleb128_size(offset);
+ emit_int8(size);
+ emit_int8(DW_OP_fbreg);
+ emit_sleb128(offset);
}
-void be_dwarf_method_begin(const ir_entity *entity)
+static void emit_function_parameters(const ir_entity *entity,
+ const parameter_dbg_info_t *infos)
+{
+ ir_type *type = get_entity_type(entity);
+ size_t n_params = get_method_n_params(type);
+ dbg_info *dbgi = get_entity_dbg_info(entity);
+ size_t i;
+ for (i = 0; i < n_params; ++i) {
+ ir_type *param_type = get_method_param_type(type, i);
+
+ if (infos != NULL && infos[i].entity != NULL) {
+ const ir_entity *entity = infos[i].entity;
+ long offset = get_entity_offset(entity);
+ emit_uleb128(DW_TAG_formal_parameter);
+ emit_string_printf("arg%u", (unsigned)i);
+ emit_dbginfo(dbgi);
+ emit_type_address(param_type);
+ emit_stack_location(offset);
+ } else {
+ emit_uleb128(abbrev_formal_parameter_no_location);
+ emit_string_printf("arg%u", (unsigned)i);
+ emit_dbginfo(dbgi);
+ emit_type_address(param_type);
+ }
+ }
+}
+
+void be_dwarf_method_before(const ir_entity *entity,
+ const parameter_dbg_info_t *parameter_infos)
{
if (debug_level < LEVEL_BASIC)
return;
+ {
+ ir_type *type = get_entity_type(entity);
+ size_t n_ress = get_method_n_ress(type);
+ size_t n_params = get_method_n_params(type);
+ size_t i;
+
+ (void)parameter_infos;
+
be_gas_emit_switch_section(GAS_SECTION_DEBUG_INFO);
+ if (n_ress > 0) {
+ ir_type *res = get_method_res_type(type, 0);
+ emit_type(res);
+ }
+ for (i = 0; i < n_params; ++i) {
+ ir_type *param_type = get_method_param_type(type, i);
+ emit_type(param_type);
+ }
+
emit_entity_label(entity);
- emit_uleb128(DW_TAG_subprogram);
+ emit_uleb128(n_ress == 0 ? abbrev_void_subprogram : DW_TAG_subprogram);
emit_string(get_entity_ld_name(entity));
emit_dbginfo(get_entity_dbg_info(entity));
+ if (n_ress > 0) {
+ ir_type *res = get_method_res_type(type, 0);
+ emit_type_address(res);
+ }
emit_int8(is_extern_entity(entity));
emit_ref(entity);
be_emit_irprintf("\t.long %smethod_end_%s\n", be_gas_get_private_prefix(),
get_entity_ld_name(entity));
+ /* frame_base prog */
+ emit_int8(1);
+ emit_int8(DW_OP_call_frame_cfa);
+
+ emit_function_parameters(entity, parameter_infos);
+ emit_int8(0);
ARR_APP1(const ir_entity*, env.pubnames_list, entity);
env.cur_ent = entity;
+ }
+}
+
+void be_dwarf_method_begin(void)
+{
+ if (debug_level < LEVEL_FRAMEINFO)
+ return;
+ be_emit_cstring("\t.cfi_startproc\n");
+ be_emit_write_line();
}
void be_dwarf_method_end(void)
const ir_entity *entity = env.cur_ent;
be_emit_irprintf("%smethod_end_%s:\n", be_gas_get_private_prefix(),
get_entity_ld_name(entity));
-}
-static void emit_type(ir_type *type);
+ if (debug_level >= LEVEL_FRAMEINFO) {
+ be_emit_cstring("\t.cfi_endproc\n");
+ be_emit_write_line();
+ }
+}
static void emit_base_type_abbrev(void)
{
be_emit_write_line();
}
-static void emit_type_address(const ir_type *type)
-{
- be_emit_irprintf("\t.long %sT%ld - %sinfo_begin\n",
- be_gas_get_private_prefix(),
- get_type_nr(type), be_gas_get_private_prefix());
- be_emit_write_line();
-}
-
static void emit_base_type(const ir_type *type)
{
char buf[128];
return;
if (get_entity_ld_name(entity)[0] == '\0')
return;
+ /* skip external variables */
+ if (get_entity_visibility(entity) == ir_visibility_external)
+ return;
be_gas_emit_switch_section(GAS_SECTION_DEBUG_INFO);
/* length of compilation unit info */
emit_size("compile_unit_begin", "compile_unit_end");
emit_label("compile_unit_begin");
- emit_int16(2); /* dwarf version */
+ emit_int16(3); /* dwarf version */
emit_address("abbrev_begin");
- emit_int8(4); /* pointer size */
+ emit_int8(4); /* pointer size, TODO: query backend */
/* compile_unit die */
emit_uleb128(DW_TAG_compile_unit);
emit_int16(language);
if (comp_dir != NULL)
emit_string(comp_dir);
+
+ /* tell gas to emit cfi in debug_frame
+ * TODO: if we produce exception handling code then this should be
+ * .eh_frame (I also wonder if bad things happen if simply always
+ * use eh_frame) */
+ be_emit_cstring("\t.cfi_sections .debug_frame\n");
+ be_emit_write_line();
}
void be_dwarf_unit_end(void)
#include "beabi.h"
+typedef struct parameter_dbg_info_t {
+ const ir_entity *entity;
+ const arch_register_t *reg;
+} parameter_dbg_info_t;
+
/** initialize and open debug handle */
void be_dwarf_open(void);
/** end compilation unit */
void be_dwarf_unit_end(void);
-/** debug for a method begin */
-void be_dwarf_method_begin(const ir_entity *ent);
+/** output debug info necessary right before defining a method */
+void be_dwarf_method_before(const ir_entity *ent,
+ const parameter_dbg_info_t *infos);
+
+/** output debug info right before beginning to output assembly instructions */
+void be_dwarf_method_begin(void);
/** debug for a method end */
void be_dwarf_method_end(void);
* assembly instructions */
void be_dwarf_location(dbg_info *dbgi);
+/** set base register that points to callframe */
+void be_dwarf_callframe_register(const arch_register_t *reg);
+
+/** set offset from base register that points to the callframe.
+ * Note: callframe is defined as in the dwarf documentation here which is the
+ * stackpointer before the call has happened. (Which would be the beginning of
+ * the between type in our backend) */
+void be_dwarf_callframe_offset(int offset);
+
+/**
+ * Indicate at which offset (relative to the CFA) a caller saved register has
+ * been saved.
+ */
+void be_dwarf_callframe_spilloffset(const arch_register_t *reg, int offset);
+
#endif
} dwarf_line_number_x_ops;
typedef enum dwarf_location_op {
- DW_OP_addr = 0x03,
- DW_OP_deref = 0x06,
- DW_OP_const1u = 0x08,
- DW_OP_const1s = 0x09,
- DW_OP_const2u = 0x0A,
- DW_OP_const2s = 0x0B,
- DW_OP_const4u = 0x0C,
- DW_OP_const4s = 0x0D,
- DW_OP_const8u = 0x0E,
- DW_OP_const8s = 0x0F,
- DW_OP_constu = 0x10,
- DW_OP_consts = 0x11,
- DW_OP_dup = 0x12,
- DW_OP_drop = 0x13,
- DW_OP_over = 0x14,
- DW_OP_pick = 0x15,
- DW_OP_swap = 0x16,
- DW_OP_rot = 0x17,
- DW_OP_xderef = 0x18,
- DW_OP_abs = 0x19,
- DW_OP_and = 0x1A,
- DW_OP_div = 0x1B,
- DW_OP_minus = 0x1C,
- DW_OP_mod = 0x1D,
- DW_OP_mul = 0x1E,
- DW_OP_neg = 0x1F,
- DW_OP_not = 0x20,
- DW_OP_or = 0x21,
- DW_OP_plus = 0x22,
- DW_OP_plus_uconst = 0x23,
- DW_OP_shl = 0x24,
- DW_OP_shr = 0x25,
- DW_OP_shra = 0x26,
- DW_OP_xor = 0x27,
- DW_OP_bra = 0x28,
- DW_OP_eq = 0x29,
- DW_OP_ge = 0x2A,
- DW_OP_gt = 0x2B,
- DW_OP_le = 0x2C,
- DW_OP_lt = 0x2D,
- DW_OP_ne = 0x2E,
- DW_OP_skip = 0x2F,
- DW_OP_lit0 = 0x30,
- DW_OP_lit1 = 0x31,
- DW_OP_lit2 = 0x32,
- DW_OP_lit3 = 0x33,
- DW_OP_lit4 = 0x34,
- DW_OP_lit5 = 0x35,
- DW_OP_lit6 = 0x36,
- DW_OP_lit7 = 0x37,
- DW_OP_lit8 = 0x38,
- DW_OP_lit9 = 0x39,
- DW_OP_lit10 = 0x3A,
- DW_OP_lit11 = 0x3B,
- DW_OP_lit12 = 0x3C,
- DW_OP_lit13 = 0x3D,
- DW_OP_lit14 = 0x3E,
- DW_OP_lit15 = 0x3F,
- DW_OP_lit16 = 0x40,
- DW_OP_lit17 = 0x41,
- DW_OP_lit18 = 0x42,
- DW_OP_lit19 = 0x43,
- DW_OP_lit20 = 0x44,
- DW_OP_lit21 = 0x45,
- DW_OP_lit22 = 0x46,
- DW_OP_lit23 = 0x47,
- DW_OP_lit24 = 0x48,
- DW_OP_lit25 = 0x49,
- DW_OP_lit26 = 0x4A,
- DW_OP_lit27 = 0x4B,
- DW_OP_lit28 = 0x4C,
- DW_OP_lit29 = 0x4D,
- DW_OP_lit30 = 0x4E,
- DW_OP_lit31 = 0x4F,
- DW_OP_reg0 = 0x50,
- DW_OP_reg1 = 0x51,
- DW_OP_reg2 = 0x52,
- DW_OP_reg3 = 0x53,
- DW_OP_reg4 = 0x54,
- DW_OP_reg5 = 0x55,
- DW_OP_reg6 = 0x56,
- DW_OP_reg7 = 0x57,
- DW_OP_reg8 = 0x58,
- DW_OP_reg9 = 0x59,
- DW_OP_reg10 = 0x5A,
- DW_OP_reg11 = 0x5B,
- DW_OP_reg12 = 0x5C,
- DW_OP_reg13 = 0x5D,
- DW_OP_reg14 = 0x5E,
- DW_OP_reg15 = 0x5F,
- DW_OP_reg16 = 0x60,
- DW_OP_reg17 = 0x61,
- DW_OP_reg18 = 0x62,
- DW_OP_reg19 = 0x63,
- DW_OP_reg20 = 0x64,
- DW_OP_reg21 = 0x65,
- DW_OP_reg22 = 0x66,
- DW_OP_reg23 = 0x67,
- DW_OP_reg24 = 0x68,
- DW_OP_reg25 = 0x69,
- DW_OP_reg26 = 0x6A,
- DW_OP_reg27 = 0x6B,
- DW_OP_reg28 = 0x6C,
- DW_OP_reg29 = 0x6D,
- DW_OP_reg30 = 0x6E,
- DW_OP_reg31 = 0x6F,
- DW_OP_breg0 = 0x70,
- DW_OP_breg1 = 0x71,
- DW_OP_breg2 = 0x72,
- DW_OP_breg3 = 0x73,
- DW_OP_breg4 = 0x74,
- DW_OP_breg5 = 0x75,
- DW_OP_breg6 = 0x76,
- DW_OP_breg7 = 0x77,
- DW_OP_breg8 = 0x78,
- DW_OP_breg9 = 0x79,
- DW_OP_breg10 = 0x7A,
- DW_OP_breg11 = 0x7B,
- DW_OP_breg12 = 0x7C,
- DW_OP_breg13 = 0x7D,
- DW_OP_breg14 = 0x7E,
- DW_OP_breg15 = 0x7F,
- DW_OP_breg16 = 0x80,
- DW_OP_breg17 = 0x81,
- DW_OP_breg18 = 0x82,
- DW_OP_breg19 = 0x83,
- DW_OP_breg20 = 0x84,
- DW_OP_breg21 = 0x85,
- DW_OP_breg22 = 0x86,
- DW_OP_breg23 = 0x87,
- DW_OP_breg24 = 0x88,
- DW_OP_breg25 = 0x89,
- DW_OP_breg26 = 0x8A,
- DW_OP_breg27 = 0x8B,
- DW_OP_breg28 = 0x8C,
- DW_OP_breg29 = 0x8D,
- DW_OP_breg30 = 0x8E,
- DW_OP_breg31 = 0x8F,
- DW_OP_regx = 0x90,
- DW_OP_fbreg = 0x91,
- DW_OP_bregx = 0x92,
- DW_OP_piece = 0x93,
- DW_OP_deref_size = 0x94,
- DW_OP_xderef_size = 0x95,
- DW_OP_nop = 0x96,
+ DW_OP_addr = 0x03,
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08,
+ DW_OP_const1s = 0x09,
+ DW_OP_const2u = 0x0A,
+ DW_OP_const2s = 0x0B,
+ DW_OP_const4u = 0x0C,
+ DW_OP_const4s = 0x0D,
+ DW_OP_const8u = 0x0E,
+ DW_OP_const8s = 0x0F,
+ DW_OP_constu = 0x10,
+ DW_OP_consts = 0x11,
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15,
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1A,
+ DW_OP_div = 0x1B,
+ DW_OP_minus = 0x1C,
+ DW_OP_mod = 0x1D,
+ DW_OP_mul = 0x1E,
+ DW_OP_neg = 0x1F,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23,
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_bra = 0x28,
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2A,
+ DW_OP_gt = 0x2B,
+ DW_OP_le = 0x2C,
+ DW_OP_lt = 0x2D,
+ DW_OP_ne = 0x2E,
+ DW_OP_skip = 0x2F,
+ DW_OP_lit0 = 0x30,
+ DW_OP_lit1 = 0x31,
+ DW_OP_lit2 = 0x32,
+ DW_OP_lit3 = 0x33,
+ DW_OP_lit4 = 0x34,
+ DW_OP_lit5 = 0x35,
+ DW_OP_lit6 = 0x36,
+ DW_OP_lit7 = 0x37,
+ DW_OP_lit8 = 0x38,
+ DW_OP_lit9 = 0x39,
+ DW_OP_lit10 = 0x3A,
+ DW_OP_lit11 = 0x3B,
+ DW_OP_lit12 = 0x3C,
+ DW_OP_lit13 = 0x3D,
+ DW_OP_lit14 = 0x3E,
+ DW_OP_lit15 = 0x3F,
+ DW_OP_lit16 = 0x40,
+ DW_OP_lit17 = 0x41,
+ DW_OP_lit18 = 0x42,
+ DW_OP_lit19 = 0x43,
+ DW_OP_lit20 = 0x44,
+ DW_OP_lit21 = 0x45,
+ DW_OP_lit22 = 0x46,
+ DW_OP_lit23 = 0x47,
+ DW_OP_lit24 = 0x48,
+ DW_OP_lit25 = 0x49,
+ DW_OP_lit26 = 0x4A,
+ DW_OP_lit27 = 0x4B,
+ DW_OP_lit28 = 0x4C,
+ DW_OP_lit29 = 0x4D,
+ DW_OP_lit30 = 0x4E,
+ DW_OP_lit31 = 0x4F,
+ DW_OP_reg0 = 0x50,
+ DW_OP_reg1 = 0x51,
+ DW_OP_reg2 = 0x52,
+ DW_OP_reg3 = 0x53,
+ DW_OP_reg4 = 0x54,
+ DW_OP_reg5 = 0x55,
+ DW_OP_reg6 = 0x56,
+ DW_OP_reg7 = 0x57,
+ DW_OP_reg8 = 0x58,
+ DW_OP_reg9 = 0x59,
+ DW_OP_reg10 = 0x5A,
+ DW_OP_reg11 = 0x5B,
+ DW_OP_reg12 = 0x5C,
+ DW_OP_reg13 = 0x5D,
+ DW_OP_reg14 = 0x5E,
+ DW_OP_reg15 = 0x5F,
+ DW_OP_reg16 = 0x60,
+ DW_OP_reg17 = 0x61,
+ DW_OP_reg18 = 0x62,
+ DW_OP_reg19 = 0x63,
+ DW_OP_reg20 = 0x64,
+ DW_OP_reg21 = 0x65,
+ DW_OP_reg22 = 0x66,
+ DW_OP_reg23 = 0x67,
+ DW_OP_reg24 = 0x68,
+ DW_OP_reg25 = 0x69,
+ DW_OP_reg26 = 0x6A,
+ DW_OP_reg27 = 0x6B,
+ DW_OP_reg28 = 0x6C,
+ DW_OP_reg29 = 0x6D,
+ DW_OP_reg30 = 0x6E,
+ DW_OP_reg31 = 0x6F,
+ DW_OP_breg0 = 0x70,
+ DW_OP_breg1 = 0x71,
+ DW_OP_breg2 = 0x72,
+ DW_OP_breg3 = 0x73,
+ DW_OP_breg4 = 0x74,
+ DW_OP_breg5 = 0x75,
+ DW_OP_breg6 = 0x76,
+ DW_OP_breg7 = 0x77,
+ DW_OP_breg8 = 0x78,
+ DW_OP_breg9 = 0x79,
+ DW_OP_breg10 = 0x7A,
+ DW_OP_breg11 = 0x7B,
+ DW_OP_breg12 = 0x7C,
+ DW_OP_breg13 = 0x7D,
+ DW_OP_breg14 = 0x7E,
+ DW_OP_breg15 = 0x7F,
+ DW_OP_breg16 = 0x80,
+ DW_OP_breg17 = 0x81,
+ DW_OP_breg18 = 0x82,
+ DW_OP_breg19 = 0x83,
+ DW_OP_breg20 = 0x84,
+ DW_OP_breg21 = 0x85,
+ DW_OP_breg22 = 0x86,
+ DW_OP_breg23 = 0x87,
+ DW_OP_breg24 = 0x88,
+ DW_OP_breg25 = 0x89,
+ DW_OP_breg26 = 0x8A,
+ DW_OP_breg27 = 0x8B,
+ DW_OP_breg28 = 0x8C,
+ DW_OP_breg29 = 0x8D,
+ DW_OP_breg30 = 0x8E,
+ DW_OP_breg31 = 0x8F,
+ DW_OP_regx = 0x90,
+ DW_OP_fbreg = 0x91,
+ DW_OP_bregx = 0x92,
+ DW_OP_piece = 0x93,
+ DW_OP_deref_size = 0x94,
+ DW_OP_xderef_size = 0x95,
+ DW_OP_nop = 0x96,
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ DW_OP_form_tls_address = 0x9b,
+ DW_OP_call_frame_cfa = 0x9c,
+ DW_OP_bit_piece = 0x9d,
} dwarf_location_op;
#endif
case GAS_SECTION_DEBUG_ABBREV: name = "section __DWARF,__debug_abbrev,regular,debug"; break;
case GAS_SECTION_DEBUG_LINE: name = "section __DWARF,__debug_line,regular,debug"; break;
case GAS_SECTION_DEBUG_PUBNAMES: name = "section __DWARF,__debug_pubnames,regular,debug"; break;
+ case GAS_SECTION_DEBUG_FRAME: name = "section __DWARF,__debug_frame,regular,debug"; break;
default: panic("unsupported scetion type 0x%X", section);
}
be_emit_irprintf("\t.%s\n", name);
"debug_abbrev",
"debug_line",
"debug_pubnames"
+ "debug_frame",
};
if (current_section == section && !(section & GAS_SECTION_FLAG_COMDAT))
{ "debug_abbrev", "progbits", "" },
{ "debug_line", "progbits", "" },
{ "debug_pubnames", "progbits", "" },
+ { "debug_frame", "progbits", "" },
};
if (be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O) {
}
}
-void be_gas_emit_function_prolog(const ir_entity *entity, unsigned po2alignment)
+void be_gas_emit_function_prolog(const ir_entity *entity, unsigned po2alignment, const parameter_dbg_info_t *parameter_infos)
{
be_gas_section_t section;
- be_dwarf_method_begin(entity);
+ be_dwarf_method_before(entity, parameter_infos);
section = determine_section(NULL, entity);
emit_section(section, entity);
/* write the begin line (makes the life easier for scripts parsing the
* assembler) */
- be_emit_write_line();
be_emit_cstring("# -- Begin ");
be_gas_emit_entity(entity);
be_emit_char('\n');
be_gas_emit_entity(entity);
be_emit_cstring(":\n");
be_emit_write_line();
+
+ be_dwarf_method_begin();
}
void be_gas_emit_function_epilog(const ir_entity *entity)
{
+ be_dwarf_method_end();
+
if (be_gas_object_file_format == OBJECT_FILE_FORMAT_ELF) {
be_emit_cstring("\t.size\t");
be_gas_emit_entity(entity);
be_emit_char('\n');
be_emit_write_line();
- be_dwarf_method_end();
-
be_emit_char('\n');
be_emit_write_line();
}
#include <stdbool.h>
#include "be_types.h"
#include "beemitter.h"
+#include "bedwarf.h"
typedef enum {
GAS_SECTION_TEXT, /**< text section - program code */
GAS_SECTION_DEBUG_ABBREV, /**< dwarf debug abbrev */
GAS_SECTION_DEBUG_LINE, /**< dwarf debug line */
GAS_SECTION_DEBUG_PUBNAMES, /**< dwarf pub names */
- GAS_SECTION_LAST = GAS_SECTION_DEBUG_PUBNAMES,
+ GAS_SECTION_DEBUG_FRAME, /**< dwarf callframe infos */
+ GAS_SECTION_LAST = GAS_SECTION_DEBUG_FRAME,
GAS_SECTION_TYPE_MASK = 0xFF,
GAS_SECTION_FLAG_TLS = 1 << 8, /**< thread local flag */
* emit assembler instructions necessary before starting function code
*/
void be_gas_emit_function_prolog(const ir_entity *entity,
- unsigned po2alignment);
+ unsigned po2alignment,
+ const parameter_dbg_info_t *paramter_infos);
void be_gas_emit_function_epilog(const ir_entity *entity);
ir_type *order[N_FRAME_TYPES]; /**< arg, between and frame types ordered. */
- ir_entity **param_map; /**< An array mapping type parameters to arg_type entries */
int initial_offset; /**< the initial difference between stack pointer and frame pointer */
int initial_bias; /**< the initial stack bias */
bool sp_relative : 1; /**< entities are addressed relative to
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)
{
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_dwarf_location(get_irn_dbg_info(block));
sched_foreach(block, 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_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);
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);
static void sparc_emit_func_prolog(ir_graph *irg)
{
ir_entity *entity = get_irg_entity(irg);
- be_gas_emit_function_prolog(entity, 4);
+ be_gas_emit_function_prolog(entity, 4, NULL);
}
/**