diff options
Diffstat (limited to 'tcg/tcg.c')
-rw-r--r-- | tcg/tcg.c | 61 |
1 files changed, 29 insertions, 32 deletions
@@ -263,37 +263,17 @@ static __attribute__((unused)) inline void tcg_patch64(tcg_insn_unit *p, static void tcg_out_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type, TCGLabel *l, intptr_t addend) { - TCGRelocation *r; + TCGRelocation *r = tcg_malloc(sizeof(TCGRelocation)); - if (l->has_value) { - /* FIXME: This may break relocations on RISC targets that - modify instruction fields in place. The caller may not have - written the initial value. */ - bool ok = patch_reloc(code_ptr, type, l->u.value, addend); - tcg_debug_assert(ok); - } else { - /* add a new relocation entry */ - r = tcg_malloc(sizeof(TCGRelocation)); - r->type = type; - r->ptr = code_ptr; - r->addend = addend; - r->next = l->u.first_reloc; - l->u.first_reloc = r; - } + r->type = type; + r->ptr = code_ptr; + r->addend = addend; + QSIMPLEQ_INSERT_TAIL(&l->relocs, r, next); } static void tcg_out_label(TCGContext *s, TCGLabel *l, tcg_insn_unit *ptr) { - intptr_t value = (intptr_t)ptr; - TCGRelocation *r; - tcg_debug_assert(!l->has_value); - - for (r = l->u.first_reloc; r != NULL; r = r->next) { - bool ok = patch_reloc(r->ptr, r->type, value, r->addend); - tcg_debug_assert(ok); - } - l->has_value = 1; l->u.value_ptr = ptr; } @@ -303,16 +283,32 @@ TCGLabel *gen_new_label(void) TCGContext *s = tcg_ctx; TCGLabel *l = tcg_malloc(sizeof(TCGLabel)); - *l = (TCGLabel){ - .id = s->nb_labels++ - }; -#ifdef CONFIG_DEBUG_TCG + memset(l, 0, sizeof(TCGLabel)); + l->id = s->nb_labels++; + QSIMPLEQ_INIT(&l->relocs); + QSIMPLEQ_INSERT_TAIL(&s->labels, l, next); -#endif return l; } +static bool tcg_resolve_relocs(TCGContext *s) +{ + TCGLabel *l; + + QSIMPLEQ_FOREACH(l, &s->labels, next) { + TCGRelocation *r; + uintptr_t value = l->u.value; + + QSIMPLEQ_FOREACH(r, &l->relocs, next) { + if (!patch_reloc(r->ptr, r->type, value, r->addend)) { + return false; + } + } + } + return true; +} + static void set_jmp_reset_offset(TCGContext *s, int which) { size_t off = tcg_current_code_size(s); @@ -1096,9 +1092,7 @@ void tcg_func_start(TCGContext *s) QTAILQ_INIT(&s->ops); QTAILQ_INIT(&s->free_ops); -#ifdef CONFIG_DEBUG_TCG QSIMPLEQ_INIT(&s->labels); -#endif } static inline TCGTemp *tcg_temp_alloc(TCGContext *s) @@ -4015,6 +4009,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) return -1; } #endif + if (!tcg_resolve_relocs(s)) { + return -2; + } /* flush instruction cache */ flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr); |