#include "util.h"
#include "obst.h"
#include "array_t.h"
-#include "be_dbgout_t.h"
+#include "irtools.h"
+#include "lc_opts.h"
+#include "lc_opts_enum.h"
#include "beabi.h"
#include "bemodule.h"
#include "beemitter.h"
#include "dbginfo.h"
#include "begnuas.h"
+enum {
+ LEVEL_NONE,
+ LEVEL_BASIC,
+ LEVEL_LOCATIONS,
+ LEVEL_FRAMEINFO
+};
+static int debug_level = LEVEL_NONE;
+
/**
* Usually we simply use the DW_TAG_xxx numbers for our abbrev IDs, but for
* the cases where we need multiple ids with the same DW_TAG we define new IDs
* here
*/
typedef enum custom_abbrevs {
- abbrev_void_pointer_type = 100,
+ abbrev_void_subprogram = 1,
+ abbrev_subprogram,
+ abbrev_formal_parameter,
abbrev_unnamed_formal_parameter,
- abbrev_void_subroutine_type,
+ abbrev_formal_parameter_no_location,
+ abbrev_variable,
+ abbrev_compile_unit,
+ abbrev_base_type,
+ abbrev_pointer_type,
+ abbrev_void_pointer_type,
+ abbrev_array_type,
+ abbrev_subrange_type,
+ abbrev_structure_type,
+ abbrev_union_type,
+ abbrev_class_type,
+ abbrev_member,
abbrev_bitfield_member,
+ abbrev_subroutine_type,
+ abbrev_void_subroutine_type,
} custom_abbrevs;
/**
* The dwarf handle.
*/
typedef struct dwarf_t {
- dbg_handle base; /**< the base class */
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;
unsigned last_line;
} dwarf_t;
+static dwarf_t env;
+
static dwarf_source_language language;
-static const char *comp_dir;
+static char *comp_dir;
-static unsigned insert_file(dwarf_t *env, const char *filename)
+static unsigned insert_file(const char *filename)
{
unsigned num;
- void *entry = pmap_get(env->file_map, filename);
+ void *entry = pmap_get(void, env.file_map, filename);
if (entry != NULL) {
return PTR_TO_INT(entry);
}
- 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));
+ 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();
}
emit_uleb128(form);
}
-static void begin_abbrev(unsigned code, dwarf_tag tag, dw_children children)
+static void begin_abbrev(custom_abbrevs code, dwarf_tag tag,
+ dw_children children)
{
emit_uleb128(code);
emit_uleb128(tag);
emit_uleb128(0);
}
-static void emit_line_info(dwarf_t *env)
+static void emit_line_info(void)
{
be_gas_emit_switch_section(GAS_SECTION_DEBUG_LINE);
emit_int8(0);
/* file list */
- for (i = 0; i < ARR_LEN(env->file_list); ++i) {
- emit_string(env->file_list[i]);
+ for (i = 0; i < ARR_LEN(env.file_list); ++i) {
+ emit_string(env.file_list[i]);
emit_uleb128(1); /* directory */
emit_uleb128(0); /* modification time */
emit_uleb128(0); /* file length */
}
}
-static void emit_pubnames(dwarf_t *env)
+static void emit_pubnames(void)
{
size_t i;
emit_size("info_section_begin", "info_begin");
emit_size("compile_unit_begin", "compile_unit_end");
- for (i = 0; i < ARR_LEN(env->pubnames_list); ++i) {
- const ir_entity *entity = env->pubnames_list[i];
+ for (i = 0; i < ARR_LEN(env.pubnames_list); ++i) {
+ const ir_entity *entity = env.pubnames_list[i];
be_emit_irprintf("\t.long %sE%ld - %sinfo_begin\n",
be_gas_get_private_prefix(),
get_entity_nr(entity), be_gas_get_private_prefix());
emit_label("pubnames_end");
}
-static void dwarf_set_dbg_info(dbg_handle *h, dbg_info *dbgi)
+void be_dwarf_location(dbg_info *dbgi)
{
- dwarf_t *const env = (dwarf_t*)h;
- src_loc_t const loc = ir_retrieve_dbg_info(dbgi);
- unsigned filenum;
+ src_loc_t loc;
+ unsigned filenum;
+ if (debug_level < LEVEL_LOCATIONS)
+ return;
+ loc = ir_retrieve_dbg_info(dbgi);
if (!loc.file)
return;
- filenum = insert_file(env, loc.file);
+ filenum = insert_file(loc.file);
be_emit_irprintf("\t.loc %u %u %u\n", filenum, loc.line, loc.column);
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);
- return visibility == ir_visibility_default
- || visibility == ir_visibility_external;
+ return visibility == ir_visibility_external;
}
static void emit_entity_label(const ir_entity *entity)
register_attribute(DW_AT_decl_column, DW_FORM_udata);
}
-/**
- * Emit values for DW_AT_decl_file, DW_AT_decl_line and DW_AT_decl_column.
- */
-static void emit_dbginfo(dwarf_t *env, const dbg_info *dbgi)
+static void emit_dbginfo(const dbg_info *dbgi)
{
src_loc_t const loc = ir_retrieve_dbg_info(dbgi);
- unsigned const file = loc.file ? insert_file(env, loc.file) : 0;
+ unsigned const file = loc.file ? insert_file(loc.file) : 0;
emit_uleb128(file);
emit_uleb128(loc.line);
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(abbrev_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(abbrev_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();
}
-/**
- * dump the dwarf for a method begin
- */
-static void dwarf_method_begin(dbg_handle *handle, const ir_entity *entity)
+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);
+}
+
+static void emit_function_parameters(const ir_entity *entity,
+ const parameter_dbg_info_t *infos)
{
- dwarf_t *env = (dwarf_t*)handle;
+ 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) {
+ long const offset = get_entity_offset(infos[i].entity);
+ emit_uleb128(abbrev_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;
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 : abbrev_subprogram);
emit_string(get_entity_ld_name(entity));
- emit_dbginfo(env, get_entity_dbg_info(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);
+ ARR_APP1(const ir_entity*, env.pubnames_list, entity);
- env->cur_ent = entity;
+ env.cur_ent = entity;
+ }
}
-/**
- * dump the dwarf for a method end
- */
-static void dwarf_method_end(dbg_handle *handle)
+void be_dwarf_method_begin(void)
{
- dwarf_t *env = (dwarf_t*)handle;
- const ir_entity *entity = env->cur_ent;
+ if (debug_level < LEVEL_FRAMEINFO)
+ return;
+ be_emit_cstring("\t.cfi_startproc\n");
+ be_emit_write_line();
+}
+void be_dwarf_method_end(void)
+{
+ if (debug_level < LEVEL_BASIC)
+ return;
+ 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 dwarf_types(dbg_handle *handle)
-{
- (void)handle;
+ if (debug_level >= LEVEL_FRAMEINFO) {
+ be_emit_cstring("\t.cfi_endproc\n");
+ be_emit_write_line();
+ }
}
-static void emit_type(dwarf_t *env, ir_type *type);
-
static void emit_base_type_abbrev(void)
{
- begin_abbrev(DW_TAG_base_type, DW_TAG_base_type, DW_CHILDREN_no);
+ begin_abbrev(abbrev_base_type, DW_TAG_base_type, DW_CHILDREN_no);
register_attribute(DW_AT_encoding, DW_FORM_data1);
register_attribute(DW_AT_byte_size, DW_FORM_data1);
register_attribute(DW_AT_name, DW_FORM_string);
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];
ir_print_type(buf, sizeof(buf), type);
emit_type_label(type);
- emit_uleb128(DW_TAG_base_type);
+ emit_uleb128(abbrev_base_type);
if (mode_is_int(mode)) {
/* bool hack */
if (strcmp(buf, "_Bool")==0 || strcmp(buf, "bool")==0) {
static void emit_pointer_type_abbrev(void)
{
- begin_abbrev(DW_TAG_pointer_type, DW_TAG_pointer_type, DW_CHILDREN_no);
+ begin_abbrev(abbrev_pointer_type, DW_TAG_pointer_type, DW_CHILDREN_no);
register_attribute(DW_AT_type, DW_FORM_ref4);
register_attribute(DW_AT_byte_size, DW_FORM_data1);
end_abbrev();
end_abbrev();
}
-static void emit_pointer_type(dwarf_t *env, const ir_type *type)
+static void emit_pointer_type(const ir_type *type)
{
ir_type *points_to = get_pointer_points_to_type(type);
unsigned size = get_type_size_bytes(type);
assert(size < 256);
if (!is_Primitive_type(points_to) || get_type_mode(points_to) != mode_ANY) {
- emit_type(env, points_to);
+ emit_type(points_to);
emit_type_label(type);
- emit_uleb128(DW_TAG_pointer_type);
+ emit_uleb128(abbrev_pointer_type);
emit_type_address(points_to);
} else {
emit_type_label(type);
static void emit_array_type_abbrev(void)
{
- begin_abbrev(DW_TAG_array_type, DW_TAG_array_type, DW_CHILDREN_yes);
+ begin_abbrev(abbrev_array_type, DW_TAG_array_type, DW_CHILDREN_yes);
register_attribute(DW_AT_type, DW_FORM_ref4);
end_abbrev();
- begin_abbrev(DW_TAG_subrange_type, DW_TAG_subrange_type, DW_CHILDREN_no);
+ begin_abbrev(abbrev_subrange_type, DW_TAG_subrange_type, DW_CHILDREN_no);
register_attribute(DW_AT_upper_bound, DW_FORM_udata);
end_abbrev();
}
-static void emit_array_type(dwarf_t *env, const ir_type *type)
+static void emit_array_type(const ir_type *type)
{
ir_type *element_type = get_array_element_type(type);
if (get_array_n_dimensions(type) != 1)
- panic("dwarf: multidimensional arrays no supported yet");
+ panic("multidimensional arrays no supported yet");
- emit_type(env, element_type);
+ emit_type(element_type);
emit_type_label(type);
- emit_uleb128(DW_TAG_array_type);
+ emit_uleb128(abbrev_array_type);
emit_type_address(element_type);
if (has_array_upper_bound(type, 0)) {
int bound = get_array_upper_bound_int(type, 0);
- emit_uleb128(DW_TAG_subrange_type);
+ emit_uleb128(abbrev_subrange_type);
emit_uleb128(bound);
}
static void emit_compound_type_abbrev(void)
{
- begin_abbrev(DW_TAG_structure_type, DW_TAG_structure_type, DW_CHILDREN_yes);
+ begin_abbrev(abbrev_structure_type, DW_TAG_structure_type, DW_CHILDREN_yes);
register_attribute(DW_AT_byte_size, DW_FORM_udata);
// TODO register_dbginfo_attributes();
end_abbrev();
- begin_abbrev(DW_TAG_union_type, DW_TAG_union_type, DW_CHILDREN_yes);
+ begin_abbrev(abbrev_union_type, DW_TAG_union_type, DW_CHILDREN_yes);
register_attribute(DW_AT_byte_size, DW_FORM_udata);
// TODO register_dbginfo_attributes();
end_abbrev();
- begin_abbrev(DW_TAG_class_type, DW_TAG_class_type, DW_CHILDREN_yes);
+ begin_abbrev(abbrev_class_type, DW_TAG_class_type, DW_CHILDREN_yes);
register_attribute(DW_AT_byte_size, DW_FORM_udata);
// TODO register_dbginfo_attributes();
end_abbrev();
- begin_abbrev(DW_TAG_member, DW_TAG_member, DW_CHILDREN_no);
+ begin_abbrev(abbrev_member, DW_TAG_member, DW_CHILDREN_no);
register_attribute(DW_AT_type, DW_FORM_ref4);
register_attribute(DW_AT_name, DW_FORM_string);
register_dbginfo_attributes();
emit_uleb128(value);
}
-static void emit_compound_type(dwarf_t *env, const ir_type *type)
+static void emit_compound_type(const ir_type *type)
{
size_t i;
size_t n_members = get_compound_n_members(type);
if (base != NULL)
member_type = base;
}
- emit_type(env, member_type);
+ emit_type(member_type);
}
emit_type_label(type);
if (is_Struct_type(type)) {
- emit_uleb128(DW_TAG_structure_type);
+ emit_uleb128(abbrev_structure_type);
} else if (is_Union_type(type)) {
- emit_uleb128(DW_TAG_union_type);
+ emit_uleb128(abbrev_union_type);
} else {
assert(is_Class_type(type));
- emit_uleb128(DW_TAG_class_type);
+ emit_uleb128(abbrev_class_type);
}
emit_uleb128(get_type_size_bytes(type));
for (i = 0; i < n_members; ++i) {
emit_uleb128(bit_offset);
member_type = base;
} else {
- emit_uleb128(DW_TAG_member);
+ emit_uleb128(abbrev_member);
}
emit_type_address(member_type);
emit_string(get_entity_name(member));
- emit_dbginfo(env, get_entity_dbg_info(member));
+ emit_dbginfo(get_entity_dbg_info(member));
assert(offset >= 0);
emit_int8(1 + get_uleb128_size(offset));
emit_op_plus_uconst(offset);
static void emit_subroutine_type_abbrev(void)
{
- begin_abbrev(DW_TAG_subroutine_type,
+ begin_abbrev(abbrev_subroutine_type,
DW_TAG_subroutine_type, DW_CHILDREN_yes);
register_attribute(DW_AT_prototyped, DW_FORM_flag);
register_attribute(DW_AT_type, DW_FORM_ref4);
end_abbrev();
}
-static void emit_subroutine_type(dwarf_t *env, const ir_type *type)
+static void emit_subroutine_type(const ir_type *type)
{
size_t n_params = get_method_n_params(type);
size_t n_ress = get_method_n_ress(type);
size_t i;
for (i = 0; i < n_params; ++i) {
ir_type *param_type = get_method_param_type(type, i);
- emit_type(env, param_type);
+ emit_type(param_type);
}
for (i = 0; i < n_ress; ++i) {
ir_type *res_type = get_method_res_type(type, i);
- emit_type(env, res_type);
+ emit_type(res_type);
}
emit_type_label(type);
- emit_uleb128(n_ress == 0 ? abbrev_void_subroutine_type : DW_TAG_subroutine_type);
+ emit_uleb128(n_ress == 0 ? abbrev_void_subroutine_type : abbrev_subroutine_type);
emit_int8(1); /* prototyped */
if (n_ress > 0) {
/* dwarf only supports 1 return type */
emit_int8(0);
}
-static void emit_type(dwarf_t *env, ir_type *type)
+static void emit_type(ir_type *type)
{
- if (pset_new_insert(&env->emitted_types, type))
+ if (!pset_new_insert(&env.emitted_types, type))
return;
switch (get_type_tpop_code(type)) {
- case tpo_primitive: emit_base_type(type); break;
- case tpo_pointer: emit_pointer_type(env, type); break;
- case tpo_array: emit_array_type(env, type); break;
+ case tpo_primitive: emit_base_type(type); break;
+ case tpo_pointer: emit_pointer_type(type); break;
+ case tpo_array: emit_array_type(type); break;
case tpo_class:
case tpo_struct:
- case tpo_union: emit_compound_type(env, type); break;
- case tpo_method: emit_subroutine_type(env, type); break;
+ case tpo_union: emit_compound_type(type); break;
+ case tpo_method: emit_subroutine_type(type); break;
default:
- panic("bedwarf: type %+F not implemented yet", type);
+ panic("type %+F not implemented yet", type);
}
}
static void emit_variable_abbrev(void)
{
- begin_abbrev(DW_TAG_variable, DW_TAG_variable, DW_CHILDREN_no);
+ begin_abbrev(abbrev_variable, DW_TAG_variable, DW_CHILDREN_no);
register_attribute(DW_AT_name, DW_FORM_string);
register_attribute(DW_AT_type, DW_FORM_ref4);
register_attribute(DW_AT_external, DW_FORM_flag);
end_abbrev();
}
-static void dwarf_variable(dbg_handle *handle, const ir_entity *entity)
+void be_dwarf_variable(const ir_entity *entity)
{
- dwarf_t *env = (dwarf_t*) handle;
- ir_type *type = get_entity_type(entity);
+ ir_type *type = get_entity_type(entity);
+ if (debug_level < LEVEL_BASIC)
+ return;
if (get_entity_ld_name(entity)[0] == '\0')
return;
+ if (!entity_has_definition(entity))
+ return;
be_gas_emit_switch_section(GAS_SECTION_DEBUG_INFO);
- emit_type(env, type);
+ emit_type(type);
emit_entity_label(entity);
- emit_uleb128(DW_TAG_variable);
+ emit_uleb128(abbrev_variable);
emit_string(get_entity_ld_name(entity));
emit_type_address(type);
emit_int8(is_extern_entity(entity));
- emit_dbginfo(env, get_entity_dbg_info(entity));
+ emit_dbginfo(get_entity_dbg_info(entity));
/* DW_AT_location */
emit_int8(5); /* block length */
emit_op_addr(entity);
- ARR_APP1(const ir_entity*, env->pubnames_list, entity);
+ ARR_APP1(const ir_entity*, env.pubnames_list, entity);
}
static void emit_compile_unit_abbrev(void)
{
- begin_abbrev(DW_TAG_compile_unit, DW_TAG_compile_unit, DW_CHILDREN_yes);
+ begin_abbrev(abbrev_compile_unit, DW_TAG_compile_unit, DW_CHILDREN_yes);
register_attribute(DW_AT_stmt_list, DW_FORM_data4);
register_attribute(DW_AT_producer, DW_FORM_string);
register_attribute(DW_AT_name, DW_FORM_string);
emit_uleb128(0);
}
-/**
- * start a new source object (compilation unit)
- */
-static void dwarf_unit_begin(dbg_handle *handle, const char *filename)
+void be_dwarf_unit_begin(const char *filename)
{
- (void) handle;
-
+ if (debug_level < LEVEL_BASIC)
+ return;
emit_abbrev();
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_uleb128(abbrev_compile_unit);
emit_address("line_section_begin");
emit_string_printf("libFirm (%u.%u %s)", ir_get_version_major(),
ir_get_version_minor(),
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();
}
-static void dwarf_unit_end(dbg_handle *handle)
+void be_dwarf_unit_end(void)
{
- dwarf_t *env = (dwarf_t*)handle;
-
+ if (debug_level < LEVEL_BASIC)
+ return;
be_gas_emit_switch_section(GAS_SECTION_TEXT);
emit_label("section_end");
emit_label("compile_unit_end");
- emit_line_info(env);
- emit_pubnames(env);
+ emit_line_info();
+ emit_pubnames();
}
-/**
- * Close the dwarf handler.
- */
-static void dwarf_close(dbg_handle *handle)
-{
- dwarf_t *h = (dwarf_t *)handle;
- pmap_destroy(h->file_map);
- DEL_ARR_F(h->file_list);
- DEL_ARR_F(h->pubnames_list);
- pset_new_destroy(&h->emitted_types);
- free(h);
-}
-
-/** The dwarf operations. */
-static const debug_ops dwarf_ops = {
- dwarf_close,
- dwarf_unit_begin,
- dwarf_unit_end,
- dwarf_method_begin,
- dwarf_method_end,
- dwarf_types,
- dwarf_variable,
- dwarf_set_dbg_info
-};
-
-/* Opens a dwarf handler */
-static dbg_handle *be_dwarf_open(void)
+void be_dwarf_close(void)
{
- dwarf_t *h = XMALLOCZ(dwarf_t);
-
- h->base.ops = &dwarf_ops;
- h->file_map = pmap_create();
- h->file_list = NEW_ARR_F(const char*, 0);
- h->pubnames_list = NEW_ARR_F(const ir_entity*, 0);
- pset_new_init(&h->emitted_types);
-
- return &h->base;
+ if (debug_level < LEVEL_BASIC)
+ return;
+ pmap_destroy(env.file_map);
+ DEL_ARR_F(env.file_list);
+ DEL_ARR_F(env.pubnames_list);
+ pset_new_destroy(&env.emitted_types);
}
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_dwarf)
-void be_init_dwarf(void)
+/* Opens a dwarf handler */
+void be_dwarf_open(void)
{
- be_register_dbgout_module("dwarf", be_dwarf_open);
+ if (debug_level < LEVEL_BASIC)
+ return;
+ env.file_map = pmap_create();
+ env.file_list = NEW_ARR_F(const char*, 0);
+ env.pubnames_list = NEW_ARR_F(const ir_entity*, 0);
+ pset_new_init(&env.emitted_types);
}
void be_dwarf_set_source_language(dwarf_source_language new_language)
void be_dwarf_set_compilation_directory(const char *new_comp_dir)
{
- comp_dir = new_comp_dir;
+ xfree(comp_dir);
+ comp_dir = xstrdup(new_comp_dir);
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_dwarf)
+void be_init_dwarf(void)
+{
+ static const lc_opt_enum_int_items_t level_items[] = {
+ { "none", LEVEL_NONE },
+ { "basic", LEVEL_BASIC },
+ { "locations", LEVEL_LOCATIONS },
+ { "frameinfo", LEVEL_FRAMEINFO },
+ { NULL, 0 }
+ };
+ static lc_opt_enum_int_var_t debug_level_opt = {
+ &debug_level, level_items
+ };
+ static lc_opt_table_entry_t be_main_options[] = {
+ LC_OPT_ENT_ENUM_INT("debug", "debug output (dwarf) level",
+ &debug_level_opt),
+ LC_OPT_LAST
+ };
+ lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
+ lc_opt_add_table(be_grp, be_main_options);
}