*/
#include "config.h"
+
+#if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
#include "dwarfwriter.h"
#include <sys/types.h>
struct _MonoDwarfWriter
{
MonoImageWriter *w;
- GHashTable *class_to_die;
+ GHashTable *class_to_die, *class_to_vtype_die, *class_to_pointer_die;
+ GHashTable *class_to_reference_die;
int fde_index, tdie_index, line_number_file_index, line_number_dir_index;
GHashTable *file_to_index, *dir_to_index;
FILE *il_file;
int il_file_line_index, loclist_index;
GSList *cie_program;
+ FILE *fp;
+ const char *temp_prefix;
+ gboolean emit_line;
};
/*
w->w = writer;
w->il_file = il_file;
+ w->fp = img_writer_get_fp (w->w);
+ w->temp_prefix = img_writer_get_temp_label_prefix (w->w);
+
return w;
}
#define ABBREV_NAMESPACE 10
#define ABBREV_VARIABLE 11
#define ABBREV_VARIABLE_LOCLIST 12
+#define ABBREV_POINTER_TYPE 13
+#define ABBREV_REFERENCE_TYPE 14
+#define ABBREV_PARAM_LOCLIST 15
+#define ABBREV_INHERITANCE 16
static int compile_unit_attr [] = {
DW_AT_producer ,DW_FORM_string,
DW_AT_location, DW_FORM_block1
};
+static int param_loclist_attr [] = {
+ DW_AT_name, DW_FORM_string,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_location, DW_FORM_data4
+};
+
static int base_type_attr [] = {
DW_AT_byte_size, DW_FORM_data1,
DW_AT_encoding, DW_FORM_data1,
DW_AT_type, DW_FORM_ref4
};
+static int pointer_type_attr [] = {
+ DW_AT_type, DW_FORM_ref4,
+};
+
+static int reference_type_attr [] = {
+ DW_AT_type, DW_FORM_ref4,
+};
+
static int enum_type_attr [] = {
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
DW_AT_type, DW_FORM_ref4,
DW_AT_location, DW_FORM_data4
};
+
+static int inheritance_attr [] = {
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_data_member_location, DW_FORM_block1
+};
typedef struct DwarfBasicType {
const char *die_name, *name;
static void
emit_line_number_info_begin (MonoDwarfWriter *w)
{
- if (!w->il_file) {
- /* FIXME: This doesn't seem to work with !xdebug */
- emit_section_change (w, ".debug_line", 0);
- emit_label (w, ".Ldebug_line_start");
- emit_label (w, ".Ldebug_line_section_start");
- return;
- }
-
/* Line number info header */
/*
* GAS seems to emit its own data to the end of the first subsection, so we use
emit_label (w, ".Ldebug_line_end");
}
+/*
+ * Some assemblers like apple's do not support subsections, so we can't place
+ * .Ldebug_info_end at the end of the section using subsections. Instead, we
+ * define it every time something gets added to the .debug_info section.
+ * The apple assember seems to use the last definition.
+ */
+static void
+emit_debug_info_end (MonoDwarfWriter *w)
+{
+ if (!img_writer_subsections_supported (w->w))
+ fprintf (w->fp, "\n.set %sdebug_info_end,.\n", w->temp_prefix);
+}
+
void
mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_program)
{
char *s, *build_info;
int i;
+ if (!img_writer_subsections_supported (w->w))
+ /* Can't emit line number info without subsections */
+ w->emit_line = FALSE;
+ else
+ w->emit_line = TRUE;
+
w->cie_program = base_unwind_program;
emit_section_change (w, ".debug_abbrev", 0);
subprogram_attr, G_N_ELEMENTS (subprogram_attr));
emit_dwarf_abbrev (w, ABBREV_PARAM, DW_TAG_formal_parameter, FALSE,
param_attr, G_N_ELEMENTS (param_attr));
+ emit_dwarf_abbrev (w, ABBREV_PARAM_LOCLIST, DW_TAG_formal_parameter, FALSE,
+ param_loclist_attr, G_N_ELEMENTS (param_loclist_attr));
emit_dwarf_abbrev (w, ABBREV_BASE_TYPE, DW_TAG_base_type, FALSE,
base_type_attr, G_N_ELEMENTS (base_type_attr));
emit_dwarf_abbrev (w, ABBREV_STRUCT_TYPE, DW_TAG_class_type, TRUE,
variable_attr, G_N_ELEMENTS (variable_attr));
emit_dwarf_abbrev (w, ABBREV_VARIABLE_LOCLIST, DW_TAG_variable, FALSE,
variable_loclist_attr, G_N_ELEMENTS (variable_loclist_attr));
+ emit_dwarf_abbrev (w, ABBREV_POINTER_TYPE, DW_TAG_pointer_type, FALSE,
+ pointer_type_attr, G_N_ELEMENTS (pointer_type_attr));
+ emit_dwarf_abbrev (w, ABBREV_REFERENCE_TYPE, DW_TAG_reference_type, FALSE,
+ reference_type_attr, G_N_ELEMENTS (reference_type_attr));
+ emit_dwarf_abbrev (w, ABBREV_INHERITANCE, DW_TAG_inheritance, FALSE,
+ inheritance_attr, G_N_ELEMENTS (inheritance_attr));
emit_byte (w, 0);
emit_section_change (w, ".debug_info", 0);
emit_int32 (w, 0); /* .debug_abbrev offset */
emit_byte (w, sizeof (gpointer)); /* address size */
- /* Emit this into a separate section so it gets placed at the end */
- emit_section_change (w, ".debug_info", 1);
- emit_int32 (w, 0); /* close everything */
- emit_label (w, ".Ldebug_info_end");
- emit_section_change (w, ".debug_info", 0);
+ if (img_writer_subsections_supported (w->w)) {
+ /* Emit this into a separate section so it gets placed at the end */
+ emit_section_change (w, ".debug_info", 1);
+ emit_int32 (w, 0); /* close everything */
+ emit_label (w, ".Ldebug_info_end");
+ emit_section_change (w, ".debug_info", 0);
+ }
/* Compilation unit */
emit_uleb128 (w, ABBREV_COMPILE_UNIT);
emit_pointer_value (w, 0);
emit_pointer_value (w, 0);
/* offset into .debug_line section */
- emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
+ if (w->emit_line)
+ emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
+ else
+ emit_int32 (w, 0);
/* Base types */
for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
emit_string (w, basic_types [i].name);
}
+ emit_debug_info_end (w);
+
/* debug_loc section */
emit_section_change (w, ".debug_loc", 0);
emit_label (w, ".Ldebug_loc_start");
/* debug_line section */
- emit_line_number_info_begin (w);
+ if (w->emit_line)
+ emit_line_number_info_begin (w);
emit_cie (w);
}
+static const char* emit_type (MonoDwarfWriter *w, MonoType *t);
+
/* Returns the local symbol pointing to the emitted debug info */
static char*
-emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass)
+emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype)
{
- char *die;
- char *full_name;
+ char *die, *pointer_die, *reference_die;
+ char *full_name, *p;
gpointer iter;
MonoClassField *field;
const char *fdie;
int k;
gboolean emit_namespace = FALSE;
+ GHashTable *cache;
// FIXME: Appdomains
if (!w->class_to_die)
w->class_to_die = g_hash_table_new (NULL, NULL);
+ if (!w->class_to_vtype_die)
+ w->class_to_vtype_die = g_hash_table_new (NULL, NULL);
+ if (!w->class_to_pointer_die)
+ w->class_to_pointer_die = g_hash_table_new (NULL, NULL);
+ if (!w->class_to_reference_die)
+ w->class_to_reference_die = g_hash_table_new (NULL, NULL);
+
+ if (vtype)
+ cache = w->class_to_vtype_die;
+ else
+ cache = w->class_to_die;
- die = g_hash_table_lookup (w->class_to_die, klass);
+ die = g_hash_table_lookup (cache, klass);
if (die)
return die;
- if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || klass->enumtype))
+ if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || (klass->byval_arg.type == MONO_TYPE_OBJECT) || klass->byval_arg.type == MONO_TYPE_GENERICINST || klass->enumtype || (klass->byval_arg.type == MONO_TYPE_VALUETYPE && vtype)))
return NULL;
/*
}
full_name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space ? "." : "", klass->name);
+ /*
+ * gdb doesn't support namespaces for non-C++ dwarf objects, so use _
+ * to separate components.
+ */
+ for (p = full_name; *p; p ++)
+ if (*p == '.')
+ *p = '_';
die = g_strdup_printf (".LTDIE_%d", w->tdie_index);
- emit_label (w, die);
+ pointer_die = g_strdup_printf (".LTDIE_%d_POINTER", w->tdie_index);
+ reference_die = g_strdup_printf (".LTDIE_%d_REFERENCE", w->tdie_index);
+ w->tdie_index ++;
+
+ g_hash_table_insert (w->class_to_pointer_die, klass, pointer_die);
+ g_hash_table_insert (w->class_to_reference_die, klass, reference_die);
+ g_hash_table_insert (cache, klass, die);
if (klass->enumtype) {
int size = mono_class_value_size (mono_class_from_mono_type (mono_class_enum_basetype (klass)), NULL);
+ emit_label (w, die);
+
emit_uleb128 (w, ABBREV_ENUM_TYPE);
emit_string (w, full_name);
emit_uleb128 (w, size);
}
}
} else {
+ guint8 buf [128];
+ guint8 *p;
+ char *parent_die;
+
+ if (klass->parent)
+ parent_die = emit_class_dwarf_info (w, klass->parent, FALSE);
+ else
+ parent_die = NULL;
+
+ /* Emit field types */
+ iter = NULL;
+ while ((field = mono_class_get_fields (klass, &iter))) {
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+ continue;
+
+ emit_type (w, field->type);
+ }
+
+ emit_label (w, die);
+
emit_uleb128 (w, ABBREV_STRUCT_TYPE);
emit_string (w, full_name);
emit_uleb128 (w, klass->instance_size);
+ if (parent_die) {
+ emit_uleb128 (w, ABBREV_INHERITANCE);
+ emit_symbol_diff (w, parent_die, ".Ldebug_info_start", 0);
+
+ p = buf;
+ *p ++= DW_OP_plus_uconst;
+ encode_uleb128 (0, p, &p);
+ emit_byte (w, p - buf);
+ emit_bytes (w, buf, p - buf);
+ }
+
/* Emit fields */
iter = NULL;
while ((field = mono_class_get_fields (klass, &iter))) {
- guint8 buf [128];
- guint8 *p;
-
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
- for (k = 0; k < G_N_ELEMENTS (basic_types); ++k)
- if (basic_types [k].type == field->type->type)
- break;
- if (k < G_N_ELEMENTS (basic_types) && field->type->type != MONO_TYPE_SZARRAY && field->type->type != MONO_TYPE_CLASS) {
- fdie = basic_types [k].die_name;
-
+ fdie = emit_type (w, field->type);
+ if (fdie) {
emit_uleb128 (w, ABBREV_DATA_MEMBER);
emit_string (w, field->name);
emit_symbol_diff (w, fdie, ".Ldebug_info_start", 0);
/* location */
p = buf;
*p ++= DW_OP_plus_uconst;
- encode_uleb128 (field->offset, p, &p);
+ if (klass->valuetype && vtype)
+ encode_uleb128 (field->offset - sizeof (MonoObject), p, &p);
+ else
+ encode_uleb128 (field->offset, p, &p);
emit_byte (w, p - buf);
emit_bytes (w, buf, p - buf);
emit_string (w, full_name);
emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
- g_free (full_name);
- w->tdie_index ++;
+ /* Add a pointer type */
+ emit_label (w, pointer_die);
+ emit_uleb128 (w, ABBREV_POINTER_TYPE);
+ emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
+
+ /* Add a reference type */
+ emit_label (w, reference_die);
+
+ emit_uleb128 (w, ABBREV_REFERENCE_TYPE);
+ emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
+
+ g_free (full_name);
if (emit_namespace) {
/* Namespace end */
emit_uleb128 (w, 0x0);
}
- g_hash_table_insert (w->class_to_die, klass, die);
return die;
}
-static void
-emit_var_type (MonoDwarfWriter *w, MonoType *t)
+static const char*
+emit_type (MonoDwarfWriter *w, MonoType *t)
{
MonoClass *klass = mono_class_from_mono_type (t);
int j;
const char *tdie;
+ if (t->byref) {
+ if (t->type == MONO_TYPE_VALUETYPE) {
+ tdie = emit_class_dwarf_info (w, klass, TRUE);
+ if (tdie)
+ return g_hash_table_lookup (w->class_to_pointer_die, klass);
+ }
+ else {
+ tdie = emit_class_dwarf_info (w, klass, FALSE);
+ /* Should return a pointer type to a reference */
+ }
+ // FIXME:
+ t = &mono_defaults.int_class->byval_arg;
+ }
for (j = 0; j < G_N_ELEMENTS (basic_types); ++j)
if (basic_types [j].type == t->type)
break;
else {
switch (t->type) {
case MONO_TYPE_CLASS:
+ emit_class_dwarf_info (w, klass, FALSE);
+ tdie = g_hash_table_lookup (w->class_to_reference_die, klass);
+ //tdie = ".LDIE_OBJECT";
+ break;
case MONO_TYPE_ARRAY:
tdie = ".LDIE_OBJECT";
break;
case MONO_TYPE_VALUETYPE:
if (klass->enumtype)
- tdie = emit_class_dwarf_info (w, klass);
+ tdie = emit_class_dwarf_info (w, klass, FALSE);
else
tdie = ".LDIE_I4";
break;
+ case MONO_TYPE_GENERICINST:
+ if (!MONO_TYPE_ISSTRUCT (t)) {
+ emit_class_dwarf_info (w, klass, FALSE);
+ tdie = g_hash_table_lookup (w->class_to_reference_die, klass);
+ } else {
+ tdie = ".LDIE_I4";
+ }
+ break;
default:
tdie = ".LDIE_I4";
break;
}
}
- if (t->byref)
- // FIXME:
- tdie = ".LDIE_I4";
+
+ return tdie;
+}
+
+static void
+emit_var_type (MonoDwarfWriter *w, MonoType *t)
+{
+ const char *tdie;
+
+ tdie = emit_type (w, t);
+
emit_symbol_diff (w, tdie, ".Ldebug_info_start", 0);
}
token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token)
{
char *res, *desc;
+ MonoMethod *cmethod;
+ MonoClass *klass;
+ MonoClassField *field;
+ gpointer data = NULL;
- if (method->wrapper_type) {
- gpointer data = mono_method_get_wrapper_data (method, token);
+ if (method->wrapper_type)
+ data = mono_method_get_wrapper_data (method, token);
- switch (*token_handler_ip) {
- case CEE_ISINST:
- case CEE_LDELEMA:
- res = g_strdup_printf ("<%s>", ((MonoClass*)data)->name);
- break;
- case CEE_NEWOBJ:
- case CEE_CALL:
- desc = mono_method_full_name (data, TRUE);
- res = g_strdup_printf ("<%s>", desc);
- g_free (desc);
- break;
- case CEE_CALLI:
+ switch (*token_handler_ip) {
+ case CEE_ISINST:
+ case CEE_CASTCLASS:
+ case CEE_LDELEMA:
+ if (method->wrapper_type)
+ klass = data;
+ else
+ klass = mono_class_get_full (method->klass->image, token, NULL);
+ res = g_strdup_printf ("<%s>", klass->name);
+ break;
+ case CEE_NEWOBJ:
+ case CEE_CALL:
+ case CEE_CALLVIRT:
+ if (method->wrapper_type)
+ cmethod = data;
+ else
+ cmethod = mono_get_method_full (method->klass->image, token, NULL, NULL);
+ desc = mono_method_full_name (cmethod, TRUE);
+ res = g_strdup_printf ("<%s>", desc);
+ g_free (desc);
+ break;
+ case CEE_CALLI:
+ if (method->wrapper_type) {
desc = mono_signature_get_desc (data, FALSE);
res = g_strdup_printf ("<%s>", desc);
g_free (desc);
- break;
- default:
- res = g_strdup_printf ("<%p>", data);
+ } else {
+ res = g_strdup_printf ("<0x%08x>", token);
}
- } else {
+ break;
+ case CEE_LDFLD:
+ case CEE_LDSFLD:
+ case CEE_STFLD:
+ case CEE_STSFLD:
+ if (method->wrapper_type)
+ field = data;
+ else
+ field = mono_field_from_token (method->klass->image, token, &klass, NULL);
+ desc = mono_field_full_name (field);
+ res = g_strdup_printf ("<%s>", desc);
+ g_free (desc);
+ break;
+ default:
res = g_strdup_printf ("<0x%08x>", token);
+ break;
}
return res;
}
}
+static gint
+compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
+{
+ if (a->native_offset == b->native_offset)
+ return a->il_offset - b->il_offset;
+ else
+ return a->native_offset - b->native_offset;
+}
+
static void
-emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, guint8 *code,
- guint32 code_size, MonoDebugMethodJitInfo *debug_info)
+emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method,
+ char *start_symbol, char *end_symbol,
+ guint8 *code, guint32 code_size,
+ MonoDebugMethodJitInfo *debug_info)
{
guint32 prev_line = 0;
guint32 prev_native_offset = 0;
char *prev_file_name = NULL;
MonoMethodHeader *header = mono_method_get_header (method);
MonoDebugMethodInfo *minfo;
+ GArray *ln_array;
+ int *native_to_il_offset = NULL;
- if (!code)
- // FIXME: The set_address op below only works with xdebug
+ if (!w->emit_line)
return;
minfo = mono_debug_lookup_method (method);
- /* FIXME: Avoid quadratic behavior */
+ /* Compute the native->IL offset mapping */
+
+ g_assert (code_size);
+
+#ifndef _EGLIB_MAJOR
+ ln_array = g_array_sized_new (FALSE, FALSE, sizeof (MonoDebugLineNumberEntry),
+ debug_info->num_line_numbers);
+ g_array_append_vals (ln_array, debug_info->line_numbers, debug_info->num_line_numbers);
+ g_array_sort (ln_array, (GCompareFunc)compare_lne);
+ native_to_il_offset = g_new0 (int, code_size + 1);
+
+ for (i = 0; i < debug_info->num_line_numbers; ++i) {
+ int j;
+ MonoDebugLineNumberEntry lne = g_array_index (ln_array, MonoDebugLineNumberEntry, i);
+
+ if (i == 0) {
+ for (j = 0; j < lne.native_offset; ++j)
+ native_to_il_offset [j] = -1;
+ }
+
+ if (i < debug_info->num_line_numbers - 1) {
+ MonoDebugLineNumberEntry lne_next = g_array_index (ln_array, MonoDebugLineNumberEntry, i + 1);
+
+ for (j = lne.native_offset; j < lne_next.native_offset; ++j)
+ native_to_il_offset [j] = lne.il_offset;
+ } else {
+ for (j = lne.native_offset; j < code_size; ++j)
+ native_to_il_offset [j] = lne.il_offset;
+ }
+ }
+ g_array_free (ln_array, TRUE);
+#endif
prev_line = 1;
prev_il_offset = -1;
if (!debug_info->line_numbers)
continue;
- /*
- * FIXME: Its hard to optimize this, since the line number info is not
- * sorted by il offset or native offset
- */
+ if (native_to_il_offset)
+ il_offset = native_to_il_offset [i];
+ else
+ il_offset = il_offset_from_address (method, debug_info, i);
+ /*
il_offset = il_offset_from_address (method, debug_info, i);
+ g_assert (il_offset == native_to_il_offset [i]);
+ */
+
+ il_offset = native_to_il_offset [i];
if (il_offset < 0)
continue;
emit_byte (w, 0);
emit_byte (w, sizeof (gpointer) + 1);
emit_byte (w, DW_LNE_set_address);
- emit_pointer_value (w, code);
+ if (start_symbol)
+ emit_pointer_unaligned (w, start_symbol);
+ else
+ emit_pointer_value (w, code);
/*
* The prolog+initlocals region does not have a line number, this
emit_byte (w, 0);
emit_byte (w, 1);
emit_byte (w, DW_LNE_end_sequence);
- } else if (code) {
+ } else if (!start_symbol) {
/* No debug info, XDEBUG mode */
char *name, *dis;
const guint8 *ip = header->code;
}
/* Emit line number info */
- prev_line = 0;
+ prev_line = 1;
prev_native_offset = 0;
for (i = 0; i < debug_info->num_line_numbers; ++i) {
MonoDebugLineNumberEntry *lne = &debug_info->line_numbers [i];
if (lne->il_offset >= header->code_size)
continue;
line = il_to_line [lne->il_offset];
- g_assert (line);
+ if (!line) {
+ /*
+ * This seems to happen randomly, it looks like il_offset points
+ * into the middle of an instruction.
+ */
+ continue;
+ /*
+ printf ("%s\n", mono_method_full_name (method, TRUE));
+ printf ("%d %d\n", lne->il_offset, header->code_size);
+ g_assert (line);
+ */
+ }
if (line - prev_line != 0) {
emit_advance_op (w, line - prev_line, (gint32)lne->native_offset - prev_native_offset);
}
}
+static MonoMethodVar*
+find_vmv (MonoCompile *cfg, MonoInst *ins)
+{
+ int j;
+
+ if (cfg->varinfo) {
+ for (j = 0; j < cfg->num_varinfo; ++j) {
+ if (cfg->varinfo [j] == ins)
+ break;
+ }
+
+ if (j < cfg->num_varinfo) {
+ return MONO_VARINFO (cfg, j);
+ }
+ }
+
+ return NULL;
+}
+
void
mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod *method, char *start_symbol, char *end_symbol, guint8 *code, guint32 code_size, MonoInst **args, MonoInst **locals, GSList *unwind_info, MonoDebugMethodJitInfo *debug_info)
{
MonoType *t;
if (i == 0 && sig->hasthis) {
- t = &method->klass->this_arg;
+ if (method->klass->valuetype)
+ t = &method->klass->this_arg;
+ else
+ t = &method->klass->byval_arg;
} else {
t = sig->params [i - sig->hasthis];
}
- emit_class_dwarf_info (w, mono_class_from_mono_type (t));
+ emit_type (w, t);
}
/* Local types */
local_tdies = g_new0 (char *, header->num_locals);
for (i = 0; i < header->num_locals; ++i) {
- emit_class_dwarf_info (w, mono_class_from_mono_type (header->locals [i]));
+ emit_type (w, header->locals [i]);
}
/* Subprogram */
MonoType *t;
const char *pname;
char pname_buf [128];
+ MonoMethodVar *vmv = NULL;
+ gboolean need_loclist = FALSE;
+
+ vmv = find_vmv (cfg, arg);
+ if (code && vmv && (vmv->live_range_start || vmv->live_range_end))
+ need_loclist = TRUE;
if (i == 0 && sig->hasthis) {
- t = &mono_defaults.object_class->byval_arg;
+ if (method->klass->valuetype)
+ t = &method->klass->this_arg;
+ else
+ t = &method->klass->byval_arg;
pname = "this";
} else {
t = sig->params [i - sig->hasthis];
pname = names [i - sig->hasthis];
}
-
- emit_uleb128 (w, ABBREV_PARAM);
+
+ emit_uleb128 (w, need_loclist ? ABBREV_PARAM_LOCLIST : ABBREV_PARAM);
/* name */
if (pname[0] == '\0') {
sprintf (pname_buf, "param%d", i - sig->hasthis);
p = buf;
encode_var_location (w, arg, p, &p);
- emit_byte (w, p - buf);
- emit_bytes (w, buf, p - buf);
+ if (need_loclist) {
+ vmv->live_range_start = 0;
+ if (vmv->live_range_end == 0)
+ /* FIXME: Uses made in calls are not recorded */
+ vmv->live_range_end = code_size;
+ emit_loclist (w, arg, code + vmv->live_range_start, code + vmv->live_range_end, buf, p - buf);
+ } else {
+ emit_byte (w, p - buf);
+ emit_bytes (w, buf, p - buf);
+ }
}
g_free (names);
gboolean need_loclist = FALSE;
/* ins->dreg no longer contains the original vreg */
- if (cfg->varinfo) {
- for (j = 0; j < cfg->num_varinfo; ++j) {
- if (cfg->varinfo [j] == ins)
- break;
- }
-
- if (code && j < cfg->num_varinfo) {
- vmv = MONO_VARINFO (cfg, j);
- if (vmv->live_range_start) {
- /* This variable has a precise live range */
- need_loclist = TRUE;
- }
+ vmv = find_vmv (cfg, ins);
+ if (code && vmv) {
+ if (vmv->live_range_start) {
+ /* This variable has a precise live range */
+ need_loclist = TRUE;
}
}
- if (need_loclist)
- emit_uleb128 (w, ABBREV_VARIABLE_LOCLIST);
- else
- emit_uleb128 (w, ABBREV_VARIABLE);
+ emit_uleb128 (w, need_loclist ? ABBREV_VARIABLE_LOCLIST : ABBREV_VARIABLE);
/* name */
for (j = 0; j < num_locals; ++j)
if (local_indexes [j] == i)
emit_line (w);
+ emit_debug_info_end (w);
+
/* Emit unwind info */
- emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
- w->fde_index ++;
+ if (unwind_info) {
+ emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
+ w->fde_index ++;
+ }
/* Emit line number info */
- if (code && debug_info)
- emit_line_number_info (w, method, code, code_size, debug_info);
+ /* != could happen when using --regression */
+ if (debug_info && (debug_info->code_start == code))
+ emit_line_number_info (w, method, start_symbol, end_symbol, code, code_size, debug_info);
emit_line (w);
}
/* Subprogram end */
emit_uleb128 (w, 0x0);
+ emit_debug_info_end (w);
+
/* Emit unwind info */
emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, FALSE);
w->fde_index ++;
}
+#endif /* End of: !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */