diff --git a/src/cpu/backend/interpreter/interpreter_backend.cc b/src/cpu/backend/interpreter/interpreter_backend.cc index d2dae765..0552acb1 100644 --- a/src/cpu/backend/interpreter/interpreter_backend.cc +++ b/src/cpu/backend/interpreter/interpreter_backend.cc @@ -11,10 +11,7 @@ AssembleContext::AssembleContext() num_instrs(0), instrs( reinterpret_cast(malloc(max_instrs * sizeof(IntInstr)))), - max_block_refs(4), - num_block_refs(0), - block_refs(reinterpret_cast( - malloc(max_block_refs * sizeof(BlockRef)))), + , num_registers(1) {} AssembleContext::~AssembleContext() { free(instrs); } @@ -30,24 +27,9 @@ IntInstr *AssembleContext::AllocInstr() { return i; } -BlockRef *AssembleContext::AllocBlockRef() { - if (num_block_refs >= max_block_refs) { - max_block_refs *= 2; - block_refs = reinterpret_cast( - realloc(block_refs, max_block_refs * sizeof(BlockRef))); - } - BlockRef *ref = &block_refs[num_block_refs++]; - memset(ref, 0, sizeof(*ref)); - return ref; -} - int AssembleContext::AllocRegister() { return num_registers++; } IntInstr *AssembleContext::TranslateInstr(Instr &ir_i, IntFn fn) { - // tag source instruction with the offset to help in resolving block - // references to instruction offsets - ir_i.set_tag(num_instrs); - IntInstr *i = AllocInstr(); i->fn = fn; TranslateValue(ir_i.arg0(), &i->arg[0]); @@ -102,15 +84,7 @@ void AssembleContext::TranslateValue(Value *ir_v, IntReg *r) { r->f64 = ir_v->value(); break; case VALUE_BLOCK: - // this argument references a block which is part of this IRBuilder. - // generate a register which will be backpatched with an actual value - // later on. - BlockRef *ref = AllocBlockRef(); - ref->block = ir_v->value(); - // store register address as offset since instrs is constantly realloced - ref->offset = - reinterpret_cast(r) - reinterpret_cast(instrs); - r->i32 = 0; + r->i32 = (int32_t)ir_v->value()->instrs().head()->tag(); break; } @@ -127,20 +101,22 @@ std::unique_ptr InterpreterBackend::AssembleBlock( IRBuilder &builder) { AssembleContext ctx; + // do an initial pass assigning ordinals to instructions so local branches + // can be resolved + int32_t ordinal = 0; + for (auto block : builder.blocks()) { + for (auto instr : block->instrs()) { + instr->set_tag((intptr_t)ordinal++); + } + } + + // translate each instruction for (auto block : builder.blocks()) { for (auto instr : block->instrs()) { ctx.TranslateInstr(*instr, GetCallback(instr)); } } - // backpatch register values containing local block addresses - for (int i = 0; i < ctx.num_block_refs; i++) { - BlockRef *ref = &ctx.block_refs[i]; - IntReg *r = reinterpret_cast( - reinterpret_cast(ctx.instrs) + ref->offset); - r->i32 = (int32_t)ref->block->instrs().head()->tag(); - } - // get number of guest cycles for the blocks const Value *md_guest_cycles = builder.GetMetadata(MD_GUEST_CYCLES); CHECK(md_guest_cycles); diff --git a/src/cpu/backend/interpreter/interpreter_backend.h b/src/cpu/backend/interpreter/interpreter_backend.h index dff4084f..a4612afa 100644 --- a/src/cpu/backend/interpreter/interpreter_backend.h +++ b/src/cpu/backend/interpreter/interpreter_backend.h @@ -32,18 +32,12 @@ struct IntInstr { intptr_t guest_op; }; -struct BlockRef { - ir::Block *block; - ptrdiff_t offset; -}; - class AssembleContext { public: AssembleContext(); ~AssembleContext(); IntInstr *AllocInstr(); - BlockRef *AllocBlockRef(); int AllocRegister(); IntInstr *TranslateInstr(ir::Instr &ir_i, IntFn fn); @@ -51,8 +45,6 @@ class AssembleContext { int max_instrs, num_instrs; IntInstr *instrs; - int max_block_refs, num_block_refs; - BlockRef *block_refs; int num_registers; };