Rewrite RTL with the new singly linked list

This commit is contained in:
2026-02-25 23:15:35 +01:00
parent c3d4449fc7
commit 68a305b00b

View File

@@ -544,7 +544,7 @@ type
next: Word;
name: Word;
length: Word;
body: Word;
body: ElnaList;
variable_map: ^ElnaSymbolTable
end;
ElnaRtlInstruction = record
@@ -771,14 +771,7 @@ begin
else
list^.last^.next := element
end;
(* TODO: This is a temporary solution for the migration from the old lists. *)
.elna_list_append_loop;
if element^.next = nil then
list^.last := element
else
element := element^.next;
goto elna_list_append_loop
end
end;
return element
end;
@@ -861,134 +854,98 @@ begin
this^.operands[n].length := operand_length
end;
proc elna_rtl_load_operand_value(tac_instruction: ^ElnaTacInstruction, operand_number: Word, into: Word);
proc elna_rtl_load_operand_value(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, operand_number: Word, into: Word);
var
result: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
operand_value: Word;
operand_length: Word;
operand_type: Word;
next_instruction: Word;
begin
operand_type := tac_instruction^.operands[operand_number].kind;
operand_value := tac_instruction^.operands[operand_number].value;
operand_length := tac_instruction^.operands[operand_number].length;
if operand_type = ElnaTacKind.immediate then
result := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.immediate, operand_value, operand_length)
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_list_append(instructions, instruction)
elsif operand_type = ElnaTacKind.symbol then
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.symbol, operand_value, operand_length);
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_list_append(instructions, instruction);
next_instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(next_instruction, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(next_instruction, 2, ElnaRtlKind.offset, into, 0);
result^.next := next_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_list_append(instructions, instruction)
elsif operand_type = ElnaTacKind.pseudo then
result := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.pseudo, operand_value, operand_length)
end;
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, operand_value, operand_length);
return result
elna_list_append(instructions, instruction)
end
end;
proc elna_rtl_load_operand_address(tac_instruction: ^ElnaTacInstruction, operand_number: Word, into: Word);
var
result: Word;
operand_value: Word;
operand_length: Word;
operand_type: Word;
proc elna_rtl_binary_operands(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction);
begin
operand_type := tac_instruction^.operands[operand_number].kind;
operand_value := tac_instruction^.operands[operand_number].value;
operand_length := tac_instruction^.operands[operand_number].length;
if operand_type = ElnaTacKind.symbol then
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.symbol, operand_value, operand_length)
elsif operand_type = ElnaTacKind.pseudo then
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.pseudo, operand_value, operand_length)
end;
return result
elna_rtl_load_operand_value(instructions, tac_instruction, 2, ElnaRtlRegister.t2);
elna_rtl_load_operand_value(instructions, tac_instruction, 3, ElnaRtlRegister.t3)
end;
proc elna_rtl_binary_operands(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction);
proc elna_rtl_binary_arithmetic(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, operation: Word);
var
lhs: ^ElnaRtlInstruction;
rhs: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
begin
lhs := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t2);
rhs := elna_rtl_load_operand_value(tac_instruction, 3, ElnaRtlRegister.t3);
elna_rtl_binary_operands(instructions, tac_instruction);
instruction := elna_rtl_instruction_create(operation);
next_instruction^ := lhs^.next;
if next_instruction^ = 0 then
lhs^.next := rhs
else
next_instruction^^ := rhs
end;
next_instruction^ := rhs^.next;
if next_instruction^ = 0 then
next_instruction^ := rhs
end;
return lhs
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
elna_list_append(instructions, instruction)
end;
proc elna_rtl_binary_arithmetic(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction, operation: Word);
proc elna_rtl_binary_equality(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, instruction_kind: Word);
var
lhs: Word;
binary_result: ^ElnaRtlInstruction;
intermediate_instruction: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
begin
lhs := elna_rtl_binary_operands(tac_instruction, next_instruction);
binary_result := elna_rtl_instruction_create(operation);
elna_rtl_binary_operands(instructions, tac_instruction);
instruction := elna_rtl_instruction_create(ElnaRtlOperator._xor);
elna_rtl_copy_operand(tac_instruction, 1, binary_result);
elna_rtl_instruction_set_operand(binary_result, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(binary_result, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
binary_result^.operator := operation;
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
elna_list_append(instructions, instruction);
intermediate_instruction := next_instruction^;
intermediate_instruction^.next := binary_result;
next_instruction^ := binary_result;
return lhs
instruction := elna_rtl_instruction_create(instruction_kind);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_list_append(instructions, instruction)
end;
proc elna_rtl_binary_equality(tac_instruction: ^ElnaTacInstruction, instruction_kind: Word, next_instruction: ^^ElnaRtlInstruction);
proc elna_rtl_binary_comparison(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction,
lhs: ElnaRtlRegister, rhs: ElnaRtlRegister);
var
operands: ^ElnaRtlInstruction;
intermediate_instruction: ^ElnaRtlInstruction;
operating_instruction: ^ElnaRtlInstruction;
binary_result: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
begin
operands := elna_rtl_binary_operands(tac_instruction, next_instruction);
operating_instruction := elna_rtl_instruction_create(ElnaRtlOperator._xor);
elna_rtl_binary_operands(instructions, tac_instruction);
elna_rtl_instruction_set_operand(operating_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(operating_instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(operating_instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, lhs, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, rhs, 0);
intermediate_instruction := next_instruction^;
intermediate_instruction^.next := operating_instruction;
elna_list_append(instructions, instruction);
binary_result := elna_rtl_instruction_create(instruction_kind);
elna_rtl_copy_operand(tac_instruction, 1, binary_result);
elna_rtl_instruction_set_operand(binary_result, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.xori);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, 1, 0);
intermediate_instruction := next_instruction^;
operating_instruction^.next := binary_result;
next_instruction^ := binary_result;
return operands
elna_list_append(instructions, instruction)
end;
proc elna_rtl_copy_operand(tac_instruction: ^ElnaTacInstruction, number: Word, rtl_instruction: Word);
@@ -1010,43 +967,38 @@ begin
end
end;
proc elna_rtl_conditional_jump(tac_instruction: Word, condition: Word);
proc elna_rtl_conditional_jump(instructions: ^ElnaList, tac_instruction: Word, condition: Word);
var
result: Word;
instruction: Word;
begin
result := elna_rtl_instruction_create(condition);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_copy_operand(tac_instruction, 2, result);
instruction := elna_rtl_instruction_create(condition);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_copy_operand(tac_instruction, 2, instruction);
return result
elna_list_append(instructions, instruction)
end;
proc elna_rtl_unary(tac_instruction: Word, rtl_operator: Word, next_instruction: Word);
proc elna_rtl_unary(instructions: ^ElnaList, tac_instruction: Word, rtl_operator: Word);
var
result: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
begin
result := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t0);
next_instruction^ := elna_rtl_instruction_create(rtl_operator);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.register, ElnaRtlRegister.t0);
result^.next := next_instruction^;
elna_rtl_load_operand_value(instructions, tac_instruction, 2, ElnaRtlRegister.t0);
return result
instruction := elna_rtl_instruction_create(rtl_operator);
elna_rtl_copy_operand(tac_instruction, 1, instructions^.first);
elna_rtl_instruction_set_operand(instructions^.first, 2, ElnaRtlKind.register, ElnaRtlRegister.t0);
elna_list_append(instructions, instruction)
end;
proc elna_rtl_call(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
proc elna_rtl_call(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var
argument_count: Word;
current_argument: ^ElnaTacOperand;
argument_move: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
current_register: Word;
first_instruction: Word;
current_instruction: Word;
variable_info: ^ElnaRtlInfo;
begin
current_register := 0;
first_instruction := nil;
current_argument := tac_instruction^.operands[2].value;
argument_count := tac_instruction^.operands[2].length;
@@ -1057,233 +1009,146 @@ begin
if current_argument^.kind = ElnaTacKind.pseudo then
variable_info := elna_symbol_table_lookup(variable_map, current_argument^.value, current_argument^.length);
(* DEBUG printf("# Sample %i %.*s\n\0", variable_info^.rtl_type^.size, current_argument^.length, current_argument^.value); *)
if variable_info^.rtl_type^.size <= 4 then
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(argument_move, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(argument_move, 2, ElnaRtlKind.pseudo,
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo,
current_argument^.value, current_argument^.length)
elsif variable_info^.rtl_type^.size <= 8 then
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(argument_move, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(argument_move, 2, ElnaRtlKind.pseudo,
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo,
current_argument^.value, current_argument^.length)
end
end;
if first_instruction = nil then
first_instruction := argument_move
else
elna_instruction_list_concatenate(current_instruction, argument_move)
end;
current_instruction := argument_move;
elna_list_append(instructions, instruction);
current_argument := current_argument + #size(ElnaTacOperand);
current_register := current_register + 1;
goto elna_rtl_call_loop
end;
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.jal);
elna_rtl_copy_operand(tac_instruction, 1, argument_move);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.jal);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_list_append(instructions, instruction);
if first_instruction = nil then
first_instruction := argument_move
else
elna_instruction_list_concatenate(current_instruction, argument_move)
end;
current_instruction := argument_move;
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(argument_move, 1, tac_instruction^.operands[3].kind,
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
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(argument_move, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0);
elna_instruction_list_concatenate(current_instruction, argument_move);
next_instruction^ := argument_move;
return first_instruction
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0);
elna_list_append(instructions, instruction)
end;
proc elna_rtl_store(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction);
proc elna_rtl_store(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction);
var
result: ^ElnaRtlInstruction;
operands: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
begin
operands := elna_rtl_load_operand_value(tac_instruction, 1, ElnaRtlRegister.t0);
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.sw);
result := operands;
operands := result^.next;
elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.t0);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
elna_rtl_instruction_set_operand(next_instruction^, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
if tac_instruction^.operands[2].kind = ElnaTacKind.pseudo then
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlKind.pseudo,
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo,
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length)
end;
if operands = nil then
result^.next := next_instruction^
else
operands^.next := next_instruction^
end;
return result
elna_list_append(instructions, instruction)
end;
proc elna_rtl_load(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction);
proc elna_rtl_load(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction);
var
result: ^ElnaRtlInstruction;
operands: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
begin
operands := elna_rtl_load_operand_value(tac_instruction, 1, ElnaRtlRegister.t0);
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.lw);
result := operands;
operands := result^.next;
elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.t0);
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlKind.offset, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(next_instruction^, 1, tac_instruction^.operands[2].kind,
instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(instruction, 1, tac_instruction^.operands[2].kind,
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length);
if operands = 0 then
result^.next := next_instruction^
else
operands^.next := next_instruction^
end;
return result
elna_list_append(instructions, instruction)
end;
proc elna_rtl_instruction(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
proc elna_rtl_instruction(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var
result: ^ElnaRtlInstruction;
operands: ^ElnaRtlInstruction;
intermediate_instruction: ^ElnaRtlInstruction;
instruction: ^ElnaRtlInstruction;
begin
result := malloc(#size(ElnaRtlInstruction));
next_instruction^ := nil;
if tac_instruction^.operator = ElnaTacOperator.get_address then
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_copy_operand(tac_instruction, 2, result)
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_copy_operand(tac_instruction, 2, instruction);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.add then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.add)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.add)
elsif tac_instruction^.operator = ElnaTacOperator.load then
result := elna_rtl_load(tac_instruction, next_instruction)
elna_rtl_load(instructions, tac_instruction)
elsif tac_instruction^.operator = ElnaTacOperator.store then
result := elna_rtl_store(tac_instruction, next_instruction)
elna_rtl_store(instructions, tac_instruction)
elsif tac_instruction^.operator = ElnaTacOperator.proc_call then
result := elna_rtl_call(tac_instruction, next_instruction, variable_map)
elna_rtl_call(instructions, tac_instruction, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.subtract then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.sub)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.sub)
elsif tac_instruction^.operator = ElnaTacOperator.multiply then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.mul)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.mul)
elsif tac_instruction^.operator = ElnaTacOperator.divide then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.div)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.div)
elsif tac_instruction^.operator = ElnaTacOperator.remainder then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.rem)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.rem)
elsif tac_instruction^.operator = ElnaTacOperator._xor then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator._xor)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator._xor)
elsif tac_instruction^.operator = ElnaTacOperator._or then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator._or)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator._or)
elsif tac_instruction^.operator = ElnaTacOperator.and then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.and)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.and)
elsif tac_instruction^.operator = ElnaTacOperator.less_than then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.slt)
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.slt)
elsif tac_instruction^.operator = ElnaTacOperator.greater_than then
operands := elna_rtl_binary_operands(tac_instruction, next_instruction);
elna_rtl_binary_operands(instructions, tac_instruction);
result := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
elna_rtl_instruction_set_operand(result, 3, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
intermediate_instruction := next_instruction^;
intermediate_instruction^.next := result;
next_instruction^ := result;
result := operands;
next_instruction^^.operator := ElnaRtlOperator.slt
instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.less_or_equal then
operands := elna_rtl_binary_operands(tac_instruction, next_instruction);
intermediate_instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_instruction_set_operand(intermediate_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(intermediate_instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
elna_rtl_instruction_set_operand(intermediate_instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
result := next_instruction^;
result^.next := intermediate_instruction;
next_instruction^ := intermediate_instruction;
result := elna_rtl_instruction_create(ElnaRtlOperator.xori);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(result, 3, ElnaRtlKind.immediate, 1, 0);
intermediate_instruction := next_instruction^;
intermediate_instruction^.next := result;
next_instruction^ := result;
result := operands
elna_rtl_binary_comparison(instructions, tac_instruction, ElnaRtlRegister.t3, ElnaRtlRegister.t2)
elsif tac_instruction^.operator = ElnaTacOperator.greater_or_equal then
operands := elna_rtl_binary_operands(tac_instruction, next_instruction);
intermediate_instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_instruction_set_operand(intermediate_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(intermediate_instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(intermediate_instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
result := next_instruction^;
result^.next := intermediate_instruction;
next_instruction^ := intermediate_instruction;
result := elna_rtl_instruction_create(ElnaRtlOperator.xori);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(result, 3, ElnaRtlKind.immediate, 1, 0);
intermediate_instruction := next_instruction^;
intermediate_instruction^.next := result;
next_instruction^ := result;
result := operands
elna_rtl_binary_comparison(instructions, tac_instruction, ElnaRtlRegister.t2, ElnaRtlRegister.t3)
elsif tac_instruction^.operator = ElnaTacOperator.equal then
result := elna_rtl_binary_equality(tac_instruction, ElnaRtlOperator.seqz, next_instruction)
elna_rtl_binary_equality(instructions, tac_instruction, ElnaRtlOperator.seqz)
elsif tac_instruction^.operator = ElnaTacOperator.not_equal then
result := elna_rtl_binary_equality(tac_instruction, ElnaRtlOperator.snez, next_instruction)
elna_rtl_binary_equality(instructions, tac_instruction, ElnaRtlOperator.snez)
elsif tac_instruction^.operator = ElnaTacOperator.negate then
result := elna_rtl_unary(tac_instruction, ElnaRtlOperator.neg, next_instruction)
elna_rtl_unary(instructions, tac_instruction, ElnaRtlOperator.neg)
elsif tac_instruction^.operator = ElnaTacOperator.complement then
result := elna_rtl_unary(tac_instruction, ElnaRtlOperator.not, next_instruction)
elna_rtl_unary(instructions, tac_instruction, ElnaRtlOperator.not)
elsif tac_instruction^.operator = ElnaTacOperator.jump then
result := elna_rtl_instruction_create(ElnaRtlOperator.j);
elna_rtl_copy_operand(tac_instruction, 1, result)
instruction := elna_rtl_instruction_create(ElnaRtlOperator.j);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.jump_if_zero then
result := elna_rtl_conditional_jump(tac_instruction, ElnaRtlOperator.beqz)
elna_rtl_conditional_jump(instructions, tac_instruction, ElnaRtlOperator.beqz)
elsif tac_instruction^.operator = ElnaTacOperator.jump_if_not_zero then
result := elna_rtl_conditional_jump(tac_instruction, ElnaRtlOperator.bnez)
elna_rtl_conditional_jump(instructions, tac_instruction, ElnaRtlOperator.bnez)
elsif tac_instruction^.operator = ElnaTacOperator._return then
result := elna_rtl_load_operand_value(tac_instruction, 1, ElnaRtlRegister.a0)
elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.a0)
elsif tac_instruction^.operator = ElnaTacOperator.label then
result := elna_rtl_instruction_create(ElnaRtlOperator.label);
elna_rtl_copy_operand(tac_instruction, 1, result)
instruction := elna_rtl_instruction_create(ElnaRtlOperator.label);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.copy then
if tac_instruction^.operands[1].kind = ElnaTacKind.pseudo then
operands := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t4);
result := operands;
operands := result^.next;
elna_rtl_load_operand_value(instructions, tac_instruction, 2, ElnaRtlRegister.t4);
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_tac_instruction_set_operand(next_instruction^, 1, ElnaRtlKind.pseudo,
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_tac_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo,
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
elna_tac_instruction_set_operand(next_instruction^, 2, ElnaRtlKind.register, ElnaRtlRegister.t4, 0);
if operands = nil then
result^.next := next_instruction^
else
operands^.next := next_instruction^
elna_tac_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t4, 0);
elna_list_append(instructions, instruction)
end
end
end;
if next_instruction^ = nil then
next_instruction^ := result;
end;
return result
end;
proc elna_tac_label(instructions: ^ElnaList, counter: Word, length: Word);
@@ -1622,32 +1487,15 @@ begin
_write_c('\n')
end;
proc elna_rtl_instructions(instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var
last_copy: ^ElnaRtlInstruction;
current_copy: ^ElnaRtlInstruction;
next_copy: ^ElnaRtlInstruction;
first_copy: ^ElnaRtlInstruction;
proc elna_rtl_instructions(instructions: ^ElnaList, instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
begin
if instruction <> nil then
first_copy := elna_rtl_instruction(instruction, @current_copy, variable_map);
instruction := instruction^.next
else
first_copy := nil;
current_copy := nil
end;
.elna_rtl_instructions_start;
if instruction <> nil then
next_copy := elna_rtl_instruction(instruction, @last_copy, variable_map);
elna_rtl_instruction(instructions, instruction, variable_map);
instruction := instruction^.next;
current_copy^.next := next_copy;
current_copy := last_copy;
goto elna_rtl_instructions_start
end;
return first_copy
goto elna_rtl_instructions_start
end
end;
proc elna_alloc_instructions(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
@@ -1678,10 +1526,10 @@ begin
.elna_alloc_procedure_loop;
temporary_variable_counter := 0;
elna_alloc_instructions(rtl_declaration^.body, rtl_declaration^.variable_map);
elna_alloc_instructions(rtl_declaration^.body.first, rtl_declaration^.variable_map);
stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.allocate_stack);
stack_instruction^.next := rtl_declaration^.body;
stack_instruction^.next := rtl_declaration^.body.first;
elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0);
rtl_declaration^.body := stack_instruction;
@@ -2137,26 +1985,37 @@ begin
end;
elna_tac_designator(instructions, unary_operand, symbol_table, @is_address, @base);
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
if operator = '@' then
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
elna_tac_copy_address(instructions, is_address, @base, operand)
elsif operator = '-' then
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
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 operator = '~' then
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.complement);
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
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 base.kind = ElnaTacKind.pseudo then
operand^.kind := base.kind;
operand^.value := base.value;
operand^.length := base.length
else
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
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);
@@ -2234,7 +2093,6 @@ end;
proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var
first_instruction: Word;
instruction: Word;
lhs: ElnaTacOperand;
rhs: ElnaTacOperand;
@@ -3541,11 +3399,10 @@ begin
return result
end;
proc elna_rtl_parameters(parameters: Word, count: Word);
proc elna_rtl_parameters(instructions: ^ElnaList, parameters: Word, count: Word);
var
result: ^ElnaRtlInstruction;
current_instruction: ^ElnaRtlInstruction;
last_instruction: Word;
instruction: ^ElnaRtlInstruction;
parameter_index: Word;
parameter_name: Word;
name_length: Word;
@@ -3560,16 +3417,10 @@ begin
name_length := parameters^;
parameters := parameters + 4;
current_instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(current_instruction, 1, ElnaRtlKind.pseudo, parameter_name, name_length);
elna_rtl_instruction_set_operand(current_instruction, 2, ElnaRtlKind.register, 11 + parameter_index, 0);
if result = nil then
result := current_instruction
else
elna_instruction_list_concatenate(last_instruction, current_instruction)
end;
last_instruction := current_instruction;
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
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_list_append(instructions, instruction);
parameter_index := parameter_index + 1;
goto elna_rtl_parameters_loop
@@ -3640,19 +3491,18 @@ end;
proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaTacProcedure);
var
result: ^ElnaRtlProcedure;
body: ^ElnaRtlInstruction;
parameters: ^ElnaRtlInstruction;
begin
result := malloc(#size(ElnaRtlProcedure));
elna_list_initialize(@result^.body);
result^.next := nil;
result^.name := tac_declaration^.name;
result^.length := tac_declaration^.length;
parameters = elna_rtl_parameters(tac_declaration^.parameters, tac_declaration^.count);
elna_rtl_parameters(@result^.body, tac_declaration^.parameters, tac_declaration^.count);
result^.variable_map := elna_rtl_symbol_table(tac_declaration^.symbol_table);
body := elna_rtl_instructions(tac_declaration^.body, result^.variable_map);
result^.body := elna_instruction_list_concatenate(parameters, body);
elna_rtl_instructions(@result^.body, tac_declaration^.body.first, result^.variable_map);
return result
end;