void MR_insert_internal_label(const char *name, MR_Code *addr, const MR_LabelLayout *label_layout) { MR_Internal *internal; MR_Internal *prev_internal; MR_do_init_label_tables(); internal = MR_GC_NEW_ATTRIB(MR_Internal, MR_ALLOC_SITE_RUNTIME); internal->MR_internal_addr = addr; internal->MR_internal_layout = label_layout; internal->MR_internal_name = name; #ifdef MR_LOWLEVEL_DEBUG if (MR_progdebug) { /* ** We can't assume that MR_LOWLEVEL_DEBUG was turned on in the code ** that generated the call to this function just because ** MR_LOWLEVEL_DEBUG is turned on here. */ if (name != NULL) { printf("inserting internal label %s at %p\n", name, addr); } else { printf("inserting internal label at %p\n", addr); } } #endif prev_internal = (MR_Internal *) MR_insert_hash_table(internal_addr_table, internal); if (prev_internal != NULL) { /* ** Two labels at same location will happen quite often, when the code ** generated between them turns out to be empty. In this case, ** MR_insert_hash_table will not have inserted internal into the table. ** ** If only one of internal and prev_internal have a layout structure, ** make sure that we associate the layout structure with the label ** address. ** ** If both internal and prev_internal have a layout structure, ** we rely on the compiler to make sure that it is ok to use ** either of their layout structures. */ if (prev_internal->MR_internal_layout == NULL) { prev_internal->MR_internal_layout = label_layout; } } }
MR_Internal * MR_lookup_internal_by_addr(const MR_Code *addr) { MR_do_init_label_tables(); MR_do_init_modules(); #ifdef MR_LOWLEVEL_DEBUG if (MR_progdebug) { printf("looking for internal label at %p\n", addr); } #endif return (MR_Internal *) MR_lookup_hash_table(internal_addr_table, addr); }
void MR_do_insert_entry_label(const char *name, MR_Code *addr, const MR_ProcLayout *entry_layout) { MR_do_init_label_tables(); #ifdef MR_MPROF_PROFILE_CALLS if (MR_profiling) { MR_prof_output_addr_decl(name, addr); } #endif /* MR_MPROF_PROFILE_CALLS */ #ifdef MR_LOWLEVEL_DEBUG if (MR_progdebug) { /* ** We can't assume that MR_LOWLEVEL_DEBUG was turned on in the code ** that generated the call to this function just because ** MR_LOWLEVEL_DEBUG is turned on here. */ if (name != NULL) { printf("recording entry label %s at %p\n", name, addr); } else { printf("recording entry label at %p\n", addr); } } #endif /* MR_LOWLEVEL_DEBUG */ #ifdef MR_NEED_ENTRY_LABEL_ARRAY if (entry_array_next >= entry_array_size) { entry_array_size *= 2; entry_array = realloc(entry_array, entry_array_size * sizeof(MR_Entry)); if (entry_array == NULL) { MR_fatal_error("run out of memory for entry label array"); } } entry_array[entry_array_next].MR_entry_addr = addr; entry_array[entry_array_next].MR_entry_name = name; entry_array[entry_array_next].MR_entry_layout = entry_layout; entry_array_next++; entry_array_sorted = MR_FALSE; #endif /* MR_NEED_ENTRY_LABEL_ARRAY */ }
MR_Entry * MR_prev_entry_by_addr(const MR_Code *addr) { int lo; int hi; int mid; int i; MR_do_init_label_tables(); MR_do_init_modules(); if (!entry_array_sorted) { qsort(entry_array, entry_array_next, sizeof(MR_Entry), compare_entry_addr); entry_array_sorted = MR_TRUE; } lo = 0; hi = entry_array_next-1; if (lo > hi || addr < entry_array[lo].MR_entry_addr) { return NULL; } while (lo <= hi) { mid = (lo + hi) / 2; if (entry_array[mid].MR_entry_addr == addr) { return &entry_array[mid]; } else if (entry_array[mid].MR_entry_addr < addr) { lo = mid + 1; } else { hi = mid - 1; } } if (lo < entry_array_next && entry_array[lo].MR_entry_addr < addr) { return &entry_array[lo]; } else { return &entry_array[lo - 1]; } }
void MR_process_all_internal_labels(void f(const void *)) { MR_do_init_label_tables(); MR_process_all_entries(internal_addr_table, f); }