dwarf: initial support for callframe and params
authorMatthias Braun <matthias.braun@kit.edu>
Wed, 25 Apr 2012 21:01:59 +0000 (23:01 +0200)
committerMatthias Braun <matthias.braun@kit.edu>
Wed, 25 Apr 2012 23:23:53 +0000 (01:23 +0200)
- We now always output dwarf3 so we can use DW_OP_call_frame_cfa and avoid
  construction location lists, but just reuse the callframe info lists.
- Backends have to emit debug info as callframe calculation changes:
  The ia32 backend has a preliminary implementation which assumes esp
  offset of frame_type_size at the beginning of a block (currently
  always true), the no-omit-fp mode assumes ebp relative addressing
  (which is correct except for the prolog/epilogue insns)

13 files changed:
ir/be/TEMPLATE/TEMPLATE_emitter.c
ir/be/amd64/amd64_emitter.c
ir/be/arm/arm_emitter.c
ir/be/arm/arm_transform.c
ir/be/beabi.c
ir/be/bedwarf.c
ir/be/bedwarf.h
ir/be/bedwarf_t.h
ir/be/begnuas.c
ir/be/begnuas.h
ir/be/beirg.h
ir/be/ia32/ia32_emitter.c
ir/be/sparc/sparc_emitter.c

index 752d348..f4a2ac2 100644 (file)
@@ -257,7 +257,7 @@ void TEMPLATE_emit_routine(ir_graph *irg)
        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);
index 1e4b370..264642a 100644 (file)
@@ -579,7 +579,7 @@ void amd64_gen_routine(ir_graph *irg)
 
        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);
 
index 3fab154..4695a57 100644 (file)
@@ -955,7 +955,7 @@ void arm_gen_routine(ir_graph *irg)
        /* 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);
 
index 95deec9..48e3dc1 100644 (file)
@@ -1695,7 +1695,6 @@ static void create_stacklayout(ir_graph *irg)
        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;
index 7b47d03..2f6ab5c 100644 (file)
@@ -313,13 +313,11 @@ static void be_abi_call_free(be_abi_call_t *call)
  * @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;
@@ -327,7 +325,6 @@ static be_stack_layout_t *stack_frame_init(be_stack_layout_t *frame, ir_type *ar
        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 */
@@ -1107,13 +1104,11 @@ static void process_calls(ir_graph *irg)
  *
  * @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);
@@ -1125,9 +1120,7 @@ static ir_type *compute_arg_type(ir_graph *irg, be_abi_call_t *call,
 
        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 */
@@ -1430,7 +1423,6 @@ static void modify_irg(ir_graph *irg)
        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));
 
@@ -1438,7 +1430,7 @@ static void modify_irg(ir_graph *irg)
 
        irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK);
 
-       arg_type = compute_arg_type(irg, call, method_type, &param_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);
@@ -1482,7 +1474,7 @@ static void modify_irg(ir_graph *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) {
index 12a86d8..c9f4e46 100644 (file)
@@ -65,7 +65,9 @@ static int debug_level = LEVEL_NONE;
 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;
 
@@ -74,7 +76,6 @@ typedef enum 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;
@@ -101,6 +102,7 @@ static unsigned insert_file(const char *filename)
        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;
@@ -140,8 +142,25 @@ static unsigned get_uleb128_size(unsigned value)
        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();
 }
@@ -307,6 +326,33 @@ void be_dwarf_location(dbg_info *dbgi)
        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);
@@ -337,38 +383,147 @@ static void emit_dbginfo(const dbg_info *dbgi)
        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)
@@ -378,9 +533,12 @@ 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)
 {
@@ -397,14 +555,6 @@ static void emit_type_label(const ir_type *type)
        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];
@@ -694,6 +844,9 @@ void be_dwarf_variable(const ir_entity *entity)
                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);
 
@@ -756,9 +909,9 @@ void be_dwarf_unit_begin(const char *filename)
        /* 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);
@@ -771,6 +924,13 @@ void be_dwarf_unit_begin(const char *filename)
                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)
index a795f60..49f4cc4 100644 (file)
 
 #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);
 
@@ -39,8 +44,12 @@ void be_dwarf_unit_begin(const char *filename);
 /** 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);
@@ -52,4 +61,19 @@ void be_dwarf_variable(const ir_entity *ent);
  * 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
index d199616..ccd7e5c 100644 (file)
@@ -217,151 +217,158 @@ typedef enum dwarf_line_number_x_ops {
 } 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
index b55f585..1839def 100644 (file)
@@ -89,6 +89,7 @@ static void emit_section_macho(be_gas_section_t section)
                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);
@@ -127,6 +128,7 @@ static void emit_section_sparc(be_gas_section_t section, const ir_entity *entity
                "debug_abbrev",
                "debug_line",
                "debug_pubnames"
+               "debug_frame",
        };
 
        if (current_section == section && !(section & GAS_SECTION_FLAG_COMDAT))
@@ -193,6 +195,7 @@ static void emit_section(be_gas_section_t section, const ir_entity *entity)
                { "debug_abbrev",   "progbits", ""   },
                { "debug_line",     "progbits", ""   },
                { "debug_pubnames", "progbits", ""   },
+               { "debug_frame",    "progbits", ""   },
        };
 
        if (be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O) {
@@ -528,18 +531,17 @@ static void emit_visibility(const ir_entity *entity)
        }
 }
 
-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');
@@ -585,10 +587,14 @@ void be_gas_emit_function_prolog(const ir_entity *entity, unsigned po2alignment)
        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);
@@ -603,8 +609,6 @@ void be_gas_emit_function_epilog(const ir_entity *entity)
        be_emit_char('\n');
        be_emit_write_line();
 
-       be_dwarf_method_end();
-
        be_emit_char('\n');
        be_emit_write_line();
 }
index 12e2aa7..43aa2e4 100644 (file)
@@ -29,6 +29,7 @@
 #include <stdbool.h>
 #include "be_types.h"
 #include "beemitter.h"
+#include "bedwarf.h"
 
 typedef enum {
        GAS_SECTION_TEXT,            /**< text section - program code */
@@ -44,7 +45,8 @@ typedef enum {
        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 */
@@ -86,7 +88,8 @@ void be_gas_emit_switch_section(be_gas_section_t section);
  * 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);
 
index 8b4e19e..b2b184d 100644 (file)
@@ -72,7 +72,6 @@ struct be_stack_layout_t {
 
        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
index 05fa271..d5c4e87 100644 (file)
@@ -89,6 +89,10 @@ 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)
 {
@@ -1661,6 +1665,15 @@ static void ia32_emit_node(ir_node *node)
                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);
+               }
+       }
 }
 
 /**
@@ -1812,6 +1825,16 @@ static void ia32_gen_block(ir_node *block)
 
        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) {
@@ -1864,6 +1887,33 @@ static int cmp_exc_entry(const void *a, const void *b)
        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.
  */
@@ -1874,6 +1924,8 @@ void ia32_gen_routine(ir_graph *irg)
        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;
@@ -1885,7 +1937,24 @@ void ia32_gen_routine(ir_graph *irg)
 
        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);
@@ -3814,12 +3883,16 @@ void ia32_gen_binary_routine(ir_graph *irg)
        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);
index f548d7c..213eec1 100644 (file)
@@ -1330,7 +1330,7 @@ static void sparc_emit_block(ir_node *block, ir_node *prev)
 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);
 }
 
 /**