From 96c6ba5087dcf3ddb09479d6b2bf47dd842d5128 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 25 Mar 2026 14:39:23 +0100 Subject: [PATCH] Add offset field to the RTL operand --- boot/stage20/cl.elna | 297 +++++++++++++++++++++++++------------------ 1 file changed, 170 insertions(+), 127 deletions(-) diff --git a/boot/stage20/cl.elna b/boot/stage20/cl.elna index bf8a1f5..1ba025b 100644 --- a/boot/stage20/cl.elna +++ b/boot/stage20/cl.elna @@ -481,6 +481,8 @@ type store, proc_call, copy, + copy_to_offset, + copy_from_offset, subtract, divide, remainder, @@ -529,6 +531,11 @@ type length: Word; body: Word end; + ElnaTacOperandType = (plain_object, dereferenced_pointer, sub_object); + ElnaTacOperandResult = record + kind: ElnaTacOperandType; + offset: Word + end; ElnaRtlOperator = ( li, @@ -560,11 +567,12 @@ type ret, nop ); - ElnaRtlKind = (register, immediate, symbol, pseudo, offset, pseudo_mem); + ElnaRtlKind = (register, immediate, symbol, pseudo, memory, pseudo_mem); ElnaRtlOperand = record kind: ElnaRtlKind; value: Word; - length: Word + length: Word; + offset: Word end; ElnaRtlStaticVariable = record next: Word; @@ -858,7 +866,7 @@ begin this^.operands[n].length := operand_length end; -proc elna_tac_instruction_create(kind: Word); +proc elna_tac_instruction_create(kind: Word) -> ^ElnaTacInstruction; var result: ^ElnaTacInstruction; begin @@ -882,11 +890,13 @@ begin return result end; -proc elna_rtl_instruction_set_operand(this: ^ElnaRtlInstruction, n: Word, operand_type: Word, operand_value: Word, operand_length: Word); +proc elna_rtl_instruction_set_operand(this: ^ElnaRtlInstruction, n: Word, operand_type: Word, + operand_value: Word, operand_length: Word, operand_offset: Word); begin this^.operands[n].kind := operand_type; this^.operands[n].value := operand_value; - this^.operands[n].length := operand_length + this^.operands[n].length := operand_length; + this^.operands[n].offset := operand_offset end; (** @@ -900,24 +910,24 @@ var begin if operand^.kind = ElnaTacKind.constant then instruction := elna_rtl_instruction_create(ElnaRtlOperator.li); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, operand^.value, operand^.length); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, operand^.value, operand^.length, 0); elna_list_append(instructions, instruction) elsif operand^.kind = ElnaTacKind.variable then pseudo_symbol := elna_symbol_table_lookup(variable_map, operand^.value, operand^.length); if pseudo_symbol = nil then instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, operand^.value, operand^.length); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, operand^.value, operand^.length, 0); elna_list_append(instructions, instruction); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, into, 0) + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, into, 0, 0) else instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, operand^.value, operand^.length) + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, operand^.value, operand^.length, 0) end; elna_list_append(instructions, instruction) end @@ -933,8 +943,8 @@ begin elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map); instruction := elna_rtl_instruction_create(ElnaRtlOperator.li); - elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, tac_operand^.value, tac_operand^.length); + elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, tac_operand^.value, tac_operand^.length, 0); elna_list_append(instructions, instruction) elsif tac_operand^.kind = ElnaTacKind.variable then pseudo_symbol := elna_symbol_table_lookup(variable_map, tac_operand^.value, tac_operand^.length); @@ -942,13 +952,13 @@ begin elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); - elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, tac_operand^.value, tac_operand^.length); + elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, tac_operand^.value, tac_operand^.length, 0); elna_list_append(instructions, instruction); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); - elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length); - elna_rtl_instruction_set_operand(instruction, 2, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length); + elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0); + elna_rtl_instruction_set_operand(instruction, 2, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0); elna_list_append(instructions, instruction) else rtl_operand^.value := tac_operand^.value; @@ -965,13 +975,13 @@ var begin result := elna_rtl_instruction_create(operation); elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.pseudo, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); elna_rtl_operand_value(instructions, @tac_instruction^.operands[2], variable_map, @rtl_operand); - elna_rtl_instruction_set_operand(result, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(result, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_rtl_operand_value(instructions, @tac_instruction^.operands[3], variable_map, @rtl_operand); - elna_rtl_instruction_set_operand(result, 3, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(result, 3, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_list_append(instructions, result); return result @@ -987,8 +997,8 @@ begin target_operand := @instruction^.operands[1]; instruction := elna_rtl_instruction_create(instruction_kind); - elna_rtl_instruction_set_operand(instruction, 1, target_operand^.kind, target_operand^.value, target_operand^.length); - elna_rtl_instruction_set_operand(instruction, 2, target_operand^.kind, target_operand^.value, target_operand^.length); + elna_rtl_instruction_set_operand(instruction, 1, target_operand^.kind, target_operand^.value, target_operand^.length, 0); + elna_rtl_instruction_set_operand(instruction, 2, target_operand^.kind, target_operand^.value, target_operand^.length, 0); elna_list_append(instructions, instruction) end; @@ -1000,13 +1010,13 @@ var begin slt_instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt); elna_rtl_instruction_set_operand(slt_instruction, 1, ElnaRtlKind.pseudo, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); elna_rtl_operand_value(instructions, @tac_instruction^.operands[2], variable_map, @rtl_operand); - elna_rtl_instruction_set_operand(slt_instruction, lhs, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(slt_instruction, lhs, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_rtl_operand_value(instructions, @tac_instruction^.operands[3], variable_map, @rtl_operand); - elna_rtl_instruction_set_operand(slt_instruction, rhs, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(slt_instruction, rhs, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_list_append(instructions, slt_instruction); return slt_instruction @@ -1023,10 +1033,10 @@ begin xor_instruction := elna_rtl_instruction_create(ElnaRtlOperator.xori); elna_rtl_instruction_set_operand(xor_instruction, 1, slt_instruction^.operands[1].kind, - slt_instruction^.operands[1].value, slt_instruction^.operands[1].length); + slt_instruction^.operands[1].value, slt_instruction^.operands[1].length, 0); elna_rtl_instruction_set_operand(xor_instruction, 2, slt_instruction^.operands[1].kind, - slt_instruction^.operands[1].value, slt_instruction^.operands[1].length); - elna_rtl_instruction_set_operand(xor_instruction, 3, ElnaRtlKind.immediate, 1, 0); + slt_instruction^.operands[1].value, slt_instruction^.operands[1].length, 0); + elna_rtl_instruction_set_operand(xor_instruction, 3, ElnaRtlKind.immediate, 1, 0, 0); elna_list_append(instructions, xor_instruction) end; @@ -1037,18 +1047,18 @@ var instruction: ^ElnaRtlInstruction; begin pseudo_symbol := elna_symbol_table_lookup(variable_map, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); if pseudo_symbol = nil then elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length) + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0) else elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length) + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0) end; elna_list_append(instructions, instruction) end; @@ -1061,9 +1071,9 @@ var begin instruction := elna_rtl_instruction_create(condition); elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand); - elna_rtl_instruction_set_operand(instruction, 1, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(instruction, 1, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); elna_list_append(instructions, instruction) end; @@ -1077,9 +1087,9 @@ begin instruction := elna_rtl_instruction_create(rtl_operator); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); - elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_list_append(instructions, instruction) end; @@ -1108,13 +1118,13 @@ begin end; instruction := elna_rtl_instruction_create(ElnaRtlOperator.jal); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.symbol, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); elna_list_append(instructions, instruction); instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv); elna_rtl_instruction_set_operand(instruction, 1, tac_instruction^.operands[3].kind, - tac_instruction^.operands[3].value, tac_instruction^.operands[3].length); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0); + tac_instruction^.operands[3].value, tac_instruction^.operands[3].length, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0, 0); elna_list_append(instructions, instruction) end; @@ -1126,9 +1136,9 @@ begin elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand); instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); - elna_rtl_instruction_set_operand(instruction, 1, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(instruction, 1, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); elna_list_append(instructions, instruction) end; @@ -1140,9 +1150,9 @@ begin elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); - elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length); + elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); elna_list_append(instructions, instruction) end; @@ -1153,30 +1163,30 @@ var target_operand: ElnaRtlOperand; pseudo_symbol: ^ElnaRtlInfo; begin - if tac_instruction^.operands[1].kind = ElnaTacKind.variable then - elna_rtl_operand_value(instructions, @tac_instruction^.operands[2], variable_map, @source_operand); + if tac_instruction^.operands[2].kind = ElnaTacKind.variable then + elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @source_operand); pseudo_symbol := elna_symbol_table_lookup(variable_map, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); if pseudo_symbol = nil then target_operand.kind := ElnaRtlKind.pseudo; elna_rtl_generate_pseudo(@target_operand.value, @target_operand.length, variable_map); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); - elna_rtl_instruction_set_operand(instruction, 1, target_operand.kind, target_operand.value, target_operand.length); + elna_rtl_instruction_set_operand(instruction, 1, target_operand.kind, target_operand.value, target_operand.length, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); elna_list_append(instructions, instruction); instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); - elna_rtl_instruction_set_operand(instruction, 1, source_operand.kind, source_operand.value, source_operand.length); - elna_rtl_instruction_set_operand(instruction, 2, target_operand.kind, target_operand.value, target_operand.length); + elna_rtl_instruction_set_operand(instruction, 1, source_operand.kind, source_operand.value, source_operand.length, 0); + elna_rtl_instruction_set_operand(instruction, 2, target_operand.kind, target_operand.value, target_operand.length, 0); elna_list_append(instructions, instruction) else instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); - elna_rtl_instruction_set_operand(instruction, 2, source_operand.kind, source_operand.value, source_operand.length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); + elna_rtl_instruction_set_operand(instruction, 2, source_operand.kind, source_operand.value, source_operand.length, 0); elna_list_append(instructions, instruction); end end @@ -1230,7 +1240,7 @@ begin elsif tac_instruction^.operator = ElnaTacOperator.jump then instruction := elna_rtl_instruction_create(ElnaRtlOperator.j); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.symbol, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); elna_list_append(instructions, instruction) elsif tac_instruction^.operator = ElnaTacOperator.jump_if_zero then elna_rtl_conditional_jump(instructions, tac_instruction, ElnaRtlOperator.beqz, variable_map) @@ -1241,7 +1251,7 @@ begin elsif tac_instruction^.operator = ElnaTacOperator.label then instruction := elna_rtl_instruction_create(ElnaRtlOperator.label); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.symbol, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); elna_list_append(instructions, instruction) elsif tac_instruction^.operator = ElnaTacOperator.copy then elna_rtl_copy(instructions, tac_instruction, variable_map) @@ -1359,8 +1369,8 @@ begin _write_c(' '); if operand_type = ElnaRtlKind.register then elna_riscv_register(instruction^.operands[n].value) - elsif operand_type = ElnaRtlKind.offset then - _write_i(instruction^.operands[n].length); + elsif operand_type = ElnaRtlKind.memory then + _write_i(instruction^.operands[n].offset); _write_c('('); elna_riscv_register(instruction^.operands[n].value); _write_c(')') @@ -1418,10 +1428,11 @@ begin pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length, variable_map); - elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); - elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter); + elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); + elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); elna_list_insert(instructions, instruction, store_instruction); instruction := store_instruction end; @@ -1437,8 +1448,8 @@ begin variable_map); instruction^.operator := ElnaRtlOperator.addi; - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.sp, 0); - elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, pseudo_symbol^.counter, 0) + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.sp, 0, 0); + elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, pseudo_symbol^.counter, 0, 0) end; if instruction^.operands[1].kind = ElnaRtlKind.pseudo then elna_alloc_operation_target(instructions, instruction, variable_map) @@ -1455,15 +1466,16 @@ begin if instruction^.operands[2].kind = ElnaRtlKind.pseudo then store_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); - elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); - elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t1, 0); + elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); + elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t1, 0, 0); pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length, variable_map); instruction^.operator := ElnaRtlOperator.lw; - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter); elna_list_insert(instructions, instruction, store_instruction); instruction := store_instruction end; @@ -1482,12 +1494,13 @@ begin memcpy(new_instruction, instruction, #size(ElnaRtlInstruction)); new_instruction^.next := nil; - elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t0, 0); + elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t0, 0, 0); instruction^.operator := ElnaRtlOperator.lw; - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter); elna_list_insert(instructions, instruction, new_instruction); instruction := new_instruction end; @@ -1509,21 +1522,24 @@ begin pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length, variable_map); instruction^.operator = ElnaRtlOperator.sw; - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter) + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter) elsif destination_pseudo then pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length, variable_map); instruction^.operator = ElnaRtlOperator.sw; elna_rtl_instruction_set_operand(instruction, 1, instruction^.operands[2].kind, - instruction^.operands[2].value, instruction^.operands[2].length); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter) + instruction^.operands[2].value, instruction^.operands[2].length, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter) elsif source_pseudo then pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length, variable_map); instruction^.operator = ElnaRtlOperator.lw; - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter) + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter) end; return instruction end; @@ -1546,12 +1562,13 @@ begin memcpy(main_instruction, instruction, #size(ElnaRtlInstruction)); main_instruction^.next := nil; - elna_rtl_instruction_set_operand(main_instruction, number, ElnaRtlKind.register, target, 0); + elna_rtl_instruction_set_operand(main_instruction, number, ElnaRtlKind.register, target, 0, 0); instruction^.operator := ElnaRtlOperator.lw; - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, target, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, target, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter); elna_list_insert(instructions, instruction, main_instruction); instruction := main_instruction end; @@ -1611,16 +1628,17 @@ begin elsif instruction^.operator = ElnaRtlOperator.beqz then if instruction^.operands[1].kind = ElnaRtlKind.pseudo then new_instruction := elna_rtl_instruction_create(ElnaRtlOperator.beqz); - elna_rtl_instruction_set_operand(new_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); + elna_rtl_instruction_set_operand(new_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); elna_rtl_instruction_set_operand(new_instruction, 2, instruction^.operands[2].kind, - instruction^.operands[2].value, instruction^.operands[2].length); + instruction^.operands[2].value, instruction^.operands[2].length, 0); pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length, variable_map); instruction^.operator := ElnaRtlOperator.lw; - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + ElnaRtlRegister.sp, 0, pseudo_symbol^.counter); elna_list_insert(instructions, instruction, new_instruction) end @@ -1733,11 +1751,11 @@ begin elna_alloc_instructions(@rtl_declaration^.body, rtl_declaration^.variable_map); stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.allocate_stack); - elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0); + elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0, 0); elna_list_prepend(@rtl_declaration^.body, stack_instruction); stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.ret); - elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0); + elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0, 0); elna_list_append(@rtl_declaration^.body, stack_instruction); @@ -2010,8 +2028,8 @@ begin elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); - elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.variable, "strings", 7); + elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.variable, "strings", 7); + elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); elna_list_append(instructions, instruction); (* Add offset to the string block pointer. *) @@ -2180,17 +2198,19 @@ begin return result end; -proc elna_tac_copy_address(instructions: ^ElnaList, is_address: Word, from: ^ElnaTacOperand, to: ^ElnaTacOperand); +proc elna_tac_copy_address(instructions: ^ElnaList, operand_type: ElnaTacOperandType, from: ^ElnaTacOperand, to: ^ElnaTacOperand); var instruction: Word; begin - if is_address then + if operand_type = ElnaTacOperandType.dereferenced_pointer then + instruction := elna_tac_instruction_create(ElnaTacOperator.copy) + elsif operand_type = ElnaTacOperandType.sub_object then instruction := elna_tac_instruction_create(ElnaTacOperator.copy) else instruction := elna_tac_instruction_create(ElnaTacOperator.get_address) end; - elna_tac_instruction_set_operand(instruction, 1, to^.kind, to^.value, to^.length); - elna_tac_instruction_set_operand(instruction, 2, from^.kind, from^.value, from^.length); + elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length); + elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length); elna_list_append(instructions, instruction) end; @@ -2200,8 +2220,8 @@ var token_kind: Word; operator: Word; unary_operand: ^ElnaTreeExpression; - is_address: Word; - instruction: Word; + operand_result: ElnaTacOperandResult; + instruction: ^ElnaTacInstruction; base: ElnaTacOperand; begin if parser_node^.kind = ElnaTreeKind.unary_expression then @@ -2211,11 +2231,11 @@ begin operator := 0; unary_operand := parser_node end; - elna_tac_designator(instructions, unary_operand, symbol_table, @is_address, @base); + elna_tac_designator(instructions, unary_operand, symbol_table, @operand_result, @base); if operator = '@' then elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - elna_tac_copy_address(instructions, is_address, @base, operand) + elna_tac_copy_address(instructions, operand_result.kind, @base, operand) elsif operator = '-' then elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); @@ -2230,7 +2250,14 @@ begin elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); elna_list_append(instructions, instruction) - elsif is_address then + elsif operand_result.kind = ElnaTacOperandType.dereferenced_pointer then + elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + + instruction := elna_tac_instruction_create(ElnaTacOperator.load); + elna_tac_instruction_set_operand(instruction, 1, base.kind, base.value, base.length); + elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); + elna_list_append(instructions, instruction) + elsif operand_result.kind = ElnaTacOperandType.sub_object then elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); instruction := elna_tac_instruction_create(ElnaTacOperator.load); @@ -2580,11 +2607,17 @@ proc elna_tac_dereference_expression(instructions: ^ElnaList, dereference_expres symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var load_instruction: Word; - is_address: Word; + operand_result: ElnaTacOperandResult; begin - elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @is_address, operand); + elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @operand_result, operand); - if is_address = true then + if operand_result.kind = ElnaTacOperandType.dereferenced_pointer then + load_instruction := elna_tac_instruction_create(ElnaTacOperator.load); + elna_tac_instruction_set_operand(load_instruction, 1, operand^.kind, operand^.value, operand^.length); + elna_tac_instruction_set_operand(load_instruction, 2, operand^.kind, operand^.value, operand^.length); + + elna_list_append(instructions, load_instruction) + elsif operand_result.kind = ElnaTacOperandType.sub_object then load_instruction := elna_tac_instruction_create(ElnaTacOperator.load); elna_tac_instruction_set_operand(load_instruction, 1, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(load_instruction, 2, operand^.kind, operand^.value, operand^.length); @@ -2593,39 +2626,41 @@ begin end end; -proc elna_tac_designator(instructions: ^ElnaList, parser_node: ^ElnaTreeExpression, symbol_table: ElnaSymbolTable, is_address: Word, operand: ^ElnaTacOperand); +proc elna_tac_designator(instructions: ^ElnaList, parser_node: ^ElnaTreeExpression, symbol_table: ElnaSymbolTable, + operand_result: ^ElnaTacOperandResult, operand: ^ElnaTacOperand); var field_access_expression: ^ElnaTreeFieldAccessExpression; designator_base: ^ElnaTreeExpression; begin + operand_result^.kind := ElnaTacOperandType.plain_object; + operand_result^.offset := 0; + if parser_node^.kind = ElnaTreeKind.dereference_expression then elna_tac_dereference_expression(instructions, parser_node, symbol_table, operand); - is_address^ := true + operand_result^.kind := ElnaTacOperandType.dereferenced_pointer elsif parser_node^.kind = ElnaTreeKind.field_access_expression then field_access_expression := parser_node; designator_base := field_access_expression^.aggregate; if designator_base^.type_decoration = nil then - elna_tac_enumeration_value(field_access_expression, operand); - is_address^ := false + elna_tac_enumeration_value(field_access_expression, operand) else - elna_tac_field_access_expression(instructions, field_access_expression, symbol_table, operand); - is_address^ := true + operand_result^.offset := elna_tac_field_access_expression(instructions, + field_access_expression, symbol_table, operand); + operand_result^.kind := ElnaTacOperandType.sub_object end elsif parser_node^.kind = ElnaTreeKind.array_access_expression then elna_tac_array_access_expression(instructions, parser_node, symbol_table, operand); - is_address^ := true + operand_result^.kind := ElnaTacOperandType.dereferenced_pointer elsif parser_node^.kind = ElnaTreeKind.call then - elna_tac_call(instructions, parser_node, symbol_table, operand); - is_address^ := false + elna_tac_call(instructions, parser_node, symbol_table, operand) else - elna_tac_simple_expression(instructions, parser_node, symbol_table, operand); - is_address^ := false + elna_tac_simple_expression(instructions, parser_node, symbol_table, operand) end end; proc elna_tac_field_access_expression(instructions: ^ElnaList, field_access_expression: ^ElnaTreeFieldAccessExpression, - symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); + symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand) -> Word; var field_type: ^ElnaType; instruction: Word; @@ -2634,13 +2669,13 @@ var field_count: Word; current_field: ^ElnaTypeField; field_offset: Word; - is_address: Word; + operand_result: ElnaTacOperandResult; base: ElnaTacOperand; begin designator_base := field_access_expression^.aggregate; aggregate_type := designator_base^.type_decoration; - elna_tac_designator(instructions, designator_base, symbol_table, @is_address, @base); + elna_tac_designator(instructions, designator_base, symbol_table, @operand_result, @base); field_count := aggregate_type^.length; current_field := aggregate_type^.members; @@ -2656,20 +2691,22 @@ begin goto elna_tac_field_access_expression_field end; elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - elna_tac_copy_address(instructions, is_address, @base, operand); + elna_tac_copy_address(instructions, operand_result.kind, @base, operand); instruction := elna_tac_instruction_create(ElnaTacOperator.add); elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.constant, field_offset, 0); elna_tac_instruction_set_operand(instruction, 3, operand^.kind, operand^.value, operand^.length); - elna_list_append(instructions, instruction) + elna_list_append(instructions, instruction); + + return field_offset end; proc elna_tac_array_access_expression(instructions: ^ElnaList, array_access_expression: ^ElnaTreeArrayAccessExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var instruction: Word; - is_address: Word; + operand_result: ElnaTacOperandResult; inter_operand: ElnaTacOperand; index_type: Word; index_value: Word; @@ -2697,10 +2734,11 @@ begin elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, element_type^.size, 0); elna_list_append(instructions, instruction); - elna_tac_designator(instructions, array_access_expression^.array, symbol_table, @is_address, @inter_operand); + elna_tac_designator(instructions, array_access_expression^.array, + symbol_table, @operand_result, @inter_operand); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - elna_tac_copy_address(instructions, is_address, @inter_operand, operand); + elna_tac_copy_address(instructions, operand_result.kind, @inter_operand, operand); instruction := elna_tac_instruction_create(ElnaTacOperator.add); elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); @@ -2729,27 +2767,32 @@ end; proc elna_tac_assign_statement(instructions: ^ElnaList, parser_tree: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable); var - is_address: Word; + operand_result: ElnaTacOperandResult; instruction: Word; assignment_operand: ElnaTacOperand; assignee: ElnaTacOperand; symbol_info: ^ElnaSymbolInfo; begin - elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @is_address, @assignee); + elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @operand_result, @assignee); (* Compile the assignment. *) elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand); - if is_address then + if operand_result.kind = ElnaTacOperandType.dereferenced_pointer then instruction := elna_tac_instruction_create(ElnaTacOperator.store); - - elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, assignment_operand.value, assignment_operand.length); + elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, + assignment_operand.value, assignment_operand.length); + elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length) + elsif operand_result.kind = ElnaTacOperandType.sub_object then + instruction := elna_tac_instruction_create(ElnaTacOperator.store); + elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, + assignment_operand.value, assignment_operand.length); elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length) else instruction := elna_tac_instruction_create(ElnaTacOperator.copy); - - elna_tac_instruction_set_operand(instruction, 1, assignee.kind, assignee.value, assignee.length); - elna_tac_instruction_set_operand(instruction, 2, assignment_operand.kind, assignment_operand.value, assignment_operand.length) + elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, + assignment_operand.value, assignment_operand.length); + elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length) end; elna_list_append(instructions, instruction) end; @@ -3565,8 +3608,8 @@ begin parameters := parameters + 4; instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, parameter_name, name_length); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, 11 + parameter_index, 0); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, parameter_name, name_length, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, 11 + parameter_index, 0, 0); elna_list_append(instructions, instruction); parameter_index := parameter_index + 1;