diff --git a/lib/compiler/compiler.lua b/lib/compiler/compiler.lua index 4d6b577..7fc4201 100644 --- a/lib/compiler/compiler.lua +++ b/lib/compiler/compiler.lua @@ -179,6 +179,11 @@ local function assemble(proto) return #bin - 3 end + local replace16 = function(pos, data) + bin[pos] = data & 0xff + bin[pos + 1] = (data >> 8) & 0xff + end + local replace32 = function(pos, data) bin[pos] = data & 0xff bin[pos + 1] = (data >> 8) & 0xff @@ -198,7 +203,14 @@ local function assemble(proto) -- constants local code_addr_pos = push32(0) -- code address, to be replaced - push32(#proto.constants + 1) -- number of constants + + -- number of constants + if proto.constants[0] then + push32(#proto.constants + 1) + else + push32(0) + end + for i=0,#proto.constants do local const = proto.constants[i] if type(const) == 'string' then @@ -218,19 +230,32 @@ local function assemble(proto) -- code push32(0) -- debug address (TODO) push32(#proto.functions + 1) -- number of functions + for i = 0, #proto.functions do + local func = proto.functions[i] local next_function_pos = #bin + 1 push32(0) -- to be replaced with next function address + + local function_start = #bin + local labels = {} + for _, inst in ipairs(func) do + -- add labels + if inst.labels then + for _, lbl in ipairs(inst.labels) do + labels[lbl] = #bin - function_start - 1 + end + end + local opcode, operand = instructions[inst[1]], inst[2] if opcode == nil then error("Unknown instruction " .. inst[1]) end if operand == nil then push8(opcode) elseif type(operand) == 'string' then - -- TODO push8(opcode) - push16(0) + table.insert(bin, operand) -- insert the label + push8(0) -- byte to be replaced (label is 16-bit) else if opcode >= 0xc0 and opcode < 0xe0 then push8(opcode) @@ -246,11 +271,22 @@ local function assemble(proto) push32(operand) end end + end + + -- replace labels + for i=function_start,#bin do + if type(bin[i]) == 'string' then + local label_addr = labels[bin[i]] + if label_addr == nil then error("Label not found: " .. bin[i]) end + replace32(i, label_addr) + end + end + replace32(next_function_pos, #bin) end - -- for _, b in ipairs(bin) do io.write(b .. ' ') end; print() + for _, b in ipairs(bin) do io.write(string.format("%02x", b) .. ' ') end; print() return string.char(table.unpack(bin)) end diff --git a/lib/priv.h b/lib/priv.h index c8d1574..4c057cf 100644 --- a/lib/priv.h +++ b/lib/priv.h @@ -78,9 +78,9 @@ typedef enum { TO_LOAD = 0X4A, // CONTROL FLOW - TO_BZ = 0XCA, - TO_BNZ = 0XCB, - TO_JMP = 0XCC, + TO_BZ = 0XAA, + TO_BNZ = 0XAB, + TO_JMP = 0XAC, // MEMORY MANAGEMENT TO_GC = 0X4B, diff --git a/test/tests.c b/test/tests.c index 1837686..d3dca4c 100644 --- a/test/tests.c +++ b/test/tests.c @@ -285,6 +285,11 @@ int main() Code* code = code_new(); assert(code_load_bytecode(code, bytecode, bytecode_sz) == T_OK); + Instruction inst = code_next_instruction(code, 0, 0); + assert(inst.operator == TO_JMP); + assert(inst.operand == 3); + assert(inst.sz == 3); + code_destroy(code); free(bytecode); }