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; next: Word;
name: Word; name: Word;
length: Word; length: Word;
body: Word; body: ElnaList;
variable_map: ^ElnaSymbolTable variable_map: ^ElnaSymbolTable
end; end;
ElnaRtlInstruction = record ElnaRtlInstruction = record
@@ -771,14 +771,7 @@ begin
else else
list^.last^.next := element list^.last^.next := element
end; 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 list^.last := element
else
element := element^.next;
goto elna_list_append_loop
end
end; end;
return element return element
end; end;
@@ -861,134 +854,98 @@ begin
this^.operands[n].length := operand_length this^.operands[n].length := operand_length
end; 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 var
result: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
operand_value: Word; operand_value: Word;
operand_length: Word; operand_length: Word;
operand_type: Word; operand_type: Word;
next_instruction: Word;
begin begin
operand_type := tac_instruction^.operands[operand_number].kind; operand_type := tac_instruction^.operands[operand_number].kind;
operand_value := tac_instruction^.operands[operand_number].value; operand_value := tac_instruction^.operands[operand_number].value;
operand_length := tac_instruction^.operands[operand_number].length; operand_length := tac_instruction^.operands[operand_number].length;
if operand_type = ElnaTacKind.immediate then if operand_type = ElnaTacKind.immediate then
result := elna_rtl_instruction_create(ElnaRtlOperator.li); instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.immediate, operand_value, operand_length) elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, operand_value, operand_length);
elna_list_append(instructions, instruction)
elsif operand_type = ElnaTacKind.symbol then elsif operand_type = ElnaTacKind.symbol then
result := elna_rtl_instruction_create(ElnaRtlOperator.la); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.symbol, operand_value, operand_length); 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); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(next_instruction, 1, ElnaRtlKind.register, into, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(next_instruction, 2, ElnaRtlKind.offset, into, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, into, 0);
elna_list_append(instructions, instruction)
result^.next := next_instruction
elsif operand_type = ElnaTacKind.pseudo then elsif operand_type = ElnaTacKind.pseudo then
result := elna_rtl_instruction_create(ElnaRtlOperator.move); instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlKind.register, into, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.pseudo, operand_value, operand_length) elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, operand_value, operand_length);
end;
return result elna_list_append(instructions, instruction)
end
end; end;
proc elna_rtl_load_operand_address(tac_instruction: ^ElnaTacInstruction, operand_number: Word, into: Word); proc elna_rtl_binary_operands(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction);
var
result: Word;
operand_value: Word;
operand_length: Word;
operand_type: Word;
begin begin
operand_type := tac_instruction^.operands[operand_number].kind; elna_rtl_load_operand_value(instructions, tac_instruction, 2, ElnaRtlRegister.t2);
operand_value := tac_instruction^.operands[operand_number].value; elna_rtl_load_operand_value(instructions, tac_instruction, 3, ElnaRtlRegister.t3)
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
end; 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 var
lhs: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
rhs: ^ElnaRtlInstruction;
begin begin
lhs := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t2); elna_rtl_binary_operands(instructions, tac_instruction);
rhs := elna_rtl_load_operand_value(tac_instruction, 3, ElnaRtlRegister.t3); instruction := elna_rtl_instruction_create(operation);
next_instruction^ := lhs^.next; elna_rtl_copy_operand(tac_instruction, 1, instruction);
if next_instruction^ = 0 then elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
lhs^.next := rhs elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
else elna_list_append(instructions, instruction)
next_instruction^^ := rhs
end;
next_instruction^ := rhs^.next;
if next_instruction^ = 0 then
next_instruction^ := rhs
end;
return lhs
end; 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 var
lhs: Word; instruction: ^ElnaRtlInstruction;
binary_result: ^ElnaRtlInstruction;
intermediate_instruction: ^ElnaRtlInstruction;
begin begin
lhs := elna_rtl_binary_operands(tac_instruction, next_instruction); elna_rtl_binary_operands(instructions, tac_instruction);
binary_result := elna_rtl_instruction_create(operation); instruction := elna_rtl_instruction_create(ElnaRtlOperator._xor);
elna_rtl_copy_operand(tac_instruction, 1, binary_result); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(binary_result, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(binary_result, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0); elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
binary_result^.operator := operation; elna_list_append(instructions, instruction);
intermediate_instruction := next_instruction^; instruction := elna_rtl_instruction_create(instruction_kind);
intermediate_instruction^.next := binary_result; elna_rtl_copy_operand(tac_instruction, 1, instruction);
next_instruction^ := binary_result; elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_list_append(instructions, instruction)
return lhs
end; 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 var
operands: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
intermediate_instruction: ^ElnaRtlInstruction;
operating_instruction: ^ElnaRtlInstruction;
binary_result: ^ElnaRtlInstruction;
begin begin
operands := elna_rtl_binary_operands(tac_instruction, next_instruction); elna_rtl_binary_operands(instructions, tac_instruction);
operating_instruction := elna_rtl_instruction_create(ElnaRtlOperator._xor);
elna_rtl_instruction_set_operand(operating_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0); instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_instruction_set_operand(operating_instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(operating_instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 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^; elna_list_append(instructions, instruction);
intermediate_instruction^.next := operating_instruction;
binary_result := elna_rtl_instruction_create(instruction_kind); instruction := elna_rtl_instruction_create(ElnaRtlOperator.xori);
elna_rtl_copy_operand(tac_instruction, 1, binary_result); elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_instruction_set_operand(binary_result, 2, 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.immediate, 1, 0);
intermediate_instruction := next_instruction^; elna_list_append(instructions, instruction)
operating_instruction^.next := binary_result;
next_instruction^ := binary_result;
return operands
end; end;
proc elna_rtl_copy_operand(tac_instruction: ^ElnaTacInstruction, number: Word, rtl_instruction: Word); proc elna_rtl_copy_operand(tac_instruction: ^ElnaTacInstruction, number: Word, rtl_instruction: Word);
@@ -1010,43 +967,38 @@ begin
end end
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 var
result: Word; instruction: Word;
begin begin
result := elna_rtl_instruction_create(condition); instruction := elna_rtl_instruction_create(condition);
elna_rtl_copy_operand(tac_instruction, 1, result); elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_copy_operand(tac_instruction, 2, result); elna_rtl_copy_operand(tac_instruction, 2, instruction);
return result elna_list_append(instructions, instruction)
end; 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 var
result: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
begin begin
result := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t0); elna_rtl_load_operand_value(instructions, 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^;
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; 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 var
argument_count: Word; argument_count: Word;
current_argument: ^ElnaTacOperand; current_argument: ^ElnaTacOperand;
argument_move: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
current_register: Word; current_register: Word;
first_instruction: Word;
current_instruction: Word;
variable_info: ^ElnaRtlInfo; variable_info: ^ElnaRtlInfo;
begin begin
current_register := 0; current_register := 0;
first_instruction := nil;
current_argument := tac_instruction^.operands[2].value; current_argument := tac_instruction^.operands[2].value;
argument_count := tac_instruction^.operands[2].length; argument_count := tac_instruction^.operands[2].length;
@@ -1057,233 +1009,146 @@ begin
if current_argument^.kind = ElnaTacKind.pseudo then if current_argument^.kind = ElnaTacKind.pseudo then
variable_info := elna_symbol_table_lookup(variable_map, current_argument^.value, current_argument^.length); 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 if variable_info^.rtl_type^.size <= 4 then
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move); instruction := 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(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(argument_move, 2, ElnaRtlKind.pseudo, elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo,
current_argument^.value, current_argument^.length) current_argument^.value, current_argument^.length)
elsif variable_info^.rtl_type^.size <= 8 then elsif variable_info^.rtl_type^.size <= 8 then
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move); instruction := 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(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(argument_move, 2, ElnaRtlKind.pseudo, elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo,
current_argument^.value, current_argument^.length) current_argument^.value, current_argument^.length)
end end
end; end;
if first_instruction = nil then elna_list_append(instructions, instruction);
first_instruction := argument_move
else
elna_instruction_list_concatenate(current_instruction, argument_move)
end;
current_instruction := argument_move;
current_argument := current_argument + #size(ElnaTacOperand); current_argument := current_argument + #size(ElnaTacOperand);
current_register := current_register + 1; current_register := current_register + 1;
goto elna_rtl_call_loop goto elna_rtl_call_loop
end; end;
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.jal); instruction := elna_rtl_instruction_create(ElnaRtlOperator.jal);
elna_rtl_copy_operand(tac_instruction, 1, argument_move); elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_list_append(instructions, instruction);
if first_instruction = nil then instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
first_instruction := argument_move elna_rtl_instruction_set_operand(instruction, 1, tac_instruction^.operands[3].kind,
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,
tac_instruction^.operands[3].value, tac_instruction^.operands[3].length); tac_instruction^.operands[3].value, tac_instruction^.operands[3].length);
elna_rtl_instruction_set_operand(argument_move, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0);
elna_instruction_list_concatenate(current_instruction, argument_move); elna_list_append(instructions, instruction)
next_instruction^ := argument_move;
return first_instruction
end; end;
proc elna_rtl_store(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction); proc elna_rtl_store(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction);
var var
result: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
operands: ^ElnaRtlInstruction;
begin begin
operands := elna_rtl_load_operand_value(tac_instruction, 1, ElnaRtlRegister.t0); elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.t0);
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.sw); instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
result := operands;
operands := result^.next;
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 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) tac_instruction^.operands[2].value, tac_instruction^.operands[2].length)
end; end;
if operands = nil then elna_list_append(instructions, instruction)
result^.next := next_instruction^
else
operands^.next := next_instruction^
end;
return result
end; end;
proc elna_rtl_load(tac_instruction: ^ElnaTacInstruction, next_instruction: ^^ElnaRtlInstruction); proc elna_rtl_load(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction);
var var
result: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
operands: ^ElnaRtlInstruction;
begin begin
operands := elna_rtl_load_operand_value(tac_instruction, 1, ElnaRtlRegister.t0); elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.t0);
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.lw);
result := operands;
operands := result^.next;
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlKind.offset, ElnaRtlRegister.t0, 0); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(next_instruction^, 1, tac_instruction^.operands[2].kind, elna_rtl_instruction_set_operand(instruction, 1, tac_instruction^.operands[2].kind,
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); tac_instruction^.operands[2].value, tac_instruction^.operands[2].length);
elna_list_append(instructions, instruction)
if operands = 0 then
result^.next := next_instruction^
else
operands^.next := next_instruction^
end;
return result
end; 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 var
result: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
operands: ^ElnaRtlInstruction;
intermediate_instruction: ^ElnaRtlInstruction;
begin begin
result := malloc(#size(ElnaRtlInstruction));
next_instruction^ := nil;
if tac_instruction^.operator = ElnaTacOperator.get_address then 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, 1, instruction);
elna_rtl_copy_operand(tac_instruction, 2, result) elna_rtl_copy_operand(tac_instruction, 2, instruction);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.add then 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 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 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 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 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 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 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 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 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 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 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 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 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); instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_copy_operand(tac_instruction, 1, result); elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlKind.register, ElnaRtlRegister.t3, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t3, 0);
elna_rtl_instruction_set_operand(result, 3, ElnaRtlKind.register, ElnaRtlRegister.t2, 0); elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t2, 0);
elna_list_append(instructions, instruction)
intermediate_instruction := next_instruction^;
intermediate_instruction^.next := result;
next_instruction^ := result;
result := operands;
next_instruction^^.operator := ElnaRtlOperator.slt
elsif tac_instruction^.operator = ElnaTacOperator.less_or_equal then elsif tac_instruction^.operator = ElnaTacOperator.less_or_equal then
operands := elna_rtl_binary_operands(tac_instruction, next_instruction); elna_rtl_binary_comparison(instructions, tac_instruction, ElnaRtlRegister.t3, ElnaRtlRegister.t2)
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
elsif tac_instruction^.operator = ElnaTacOperator.greater_or_equal then elsif tac_instruction^.operator = ElnaTacOperator.greater_or_equal then
operands := elna_rtl_binary_operands(tac_instruction, next_instruction); elna_rtl_binary_comparison(instructions, tac_instruction, ElnaRtlRegister.t2, ElnaRtlRegister.t3)
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
elsif tac_instruction^.operator = ElnaTacOperator.equal then 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 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 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 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 elsif tac_instruction^.operator = ElnaTacOperator.jump then
result := elna_rtl_instruction_create(ElnaRtlOperator.j); instruction := elna_rtl_instruction_create(ElnaRtlOperator.j);
elna_rtl_copy_operand(tac_instruction, 1, result) elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.jump_if_zero then 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 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 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 elsif tac_instruction^.operator = ElnaTacOperator.label then
result := elna_rtl_instruction_create(ElnaRtlOperator.label); instruction := elna_rtl_instruction_create(ElnaRtlOperator.label);
elna_rtl_copy_operand(tac_instruction, 1, result) elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.copy then elsif tac_instruction^.operator = ElnaTacOperator.copy then
if tac_instruction^.operands[1].kind = ElnaTacKind.pseudo then if tac_instruction^.operands[1].kind = ElnaTacKind.pseudo then
operands := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t4); elna_rtl_load_operand_value(instructions, tac_instruction, 2, ElnaRtlRegister.t4);
result := operands;
operands := result^.next;
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.move); instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_tac_instruction_set_operand(next_instruction^, 1, ElnaRtlKind.pseudo, elna_tac_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);
elna_tac_instruction_set_operand(next_instruction^, 2, ElnaRtlKind.register, ElnaRtlRegister.t4, 0); elna_tac_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t4, 0);
elna_list_append(instructions, instruction)
if operands = nil then
result^.next := next_instruction^
else
operands^.next := next_instruction^
end end
end end
end;
if next_instruction^ = nil then
next_instruction^ := result;
end;
return result
end; end;
proc elna_tac_label(instructions: ^ElnaList, counter: Word, length: Word); proc elna_tac_label(instructions: ^ElnaList, counter: Word, length: Word);
@@ -1622,32 +1487,15 @@ begin
_write_c('\n') _write_c('\n')
end; end;
proc elna_rtl_instructions(instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); proc elna_rtl_instructions(instructions: ^ElnaList, instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var
last_copy: ^ElnaRtlInstruction;
current_copy: ^ElnaRtlInstruction;
next_copy: ^ElnaRtlInstruction;
first_copy: ^ElnaRtlInstruction;
begin 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; .elna_rtl_instructions_start;
if instruction <> nil then if instruction <> nil then
next_copy := elna_rtl_instruction(instruction, @last_copy, variable_map); elna_rtl_instruction(instructions, instruction, variable_map);
instruction := instruction^.next; 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; end;
proc elna_alloc_instructions(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable); proc elna_alloc_instructions(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
@@ -1678,10 +1526,10 @@ begin
.elna_alloc_procedure_loop; .elna_alloc_procedure_loop;
temporary_variable_counter := 0; 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 := 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); elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0);
rtl_declaration^.body := stack_instruction; rtl_declaration^.body := stack_instruction;
@@ -2137,26 +1985,37 @@ begin
end; end;
elna_tac_designator(instructions, unary_operand, symbol_table, @is_address, @base); 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 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, is_address, @base, operand)
elsif operator = '-' then elsif operator = '-' then
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.negate); 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, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif operator = '~' then elsif operator = '~' then
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.complement); 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, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif is_address then elsif is_address then
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.load); 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, 1, base.kind, base.value, base.length);
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif base.kind = ElnaTacKind.pseudo then
operand^.kind := base.kind;
operand^.value := base.value;
operand^.length := base.length
else else
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.copy); 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, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.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); proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var var
first_instruction: Word;
instruction: Word; instruction: Word;
lhs: ElnaTacOperand; lhs: ElnaTacOperand;
rhs: ElnaTacOperand; rhs: ElnaTacOperand;
@@ -3541,11 +3399,10 @@ begin
return result return result
end; end;
proc elna_rtl_parameters(parameters: Word, count: Word); proc elna_rtl_parameters(instructions: ^ElnaList, parameters: Word, count: Word);
var var
result: ^ElnaRtlInstruction; result: ^ElnaRtlInstruction;
current_instruction: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
last_instruction: Word;
parameter_index: Word; parameter_index: Word;
parameter_name: Word; parameter_name: Word;
name_length: Word; name_length: Word;
@@ -3560,16 +3417,10 @@ begin
name_length := parameters^; name_length := parameters^;
parameters := parameters + 4; parameters := parameters + 4;
current_instruction := elna_rtl_instruction_create(ElnaRtlOperator.move); 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(instruction, 1, ElnaRtlKind.pseudo, parameter_name, name_length);
elna_rtl_instruction_set_operand(current_instruction, 2, ElnaRtlKind.register, 11 + parameter_index, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, 11 + parameter_index, 0);
elna_list_append(instructions, instruction);
if result = nil then
result := current_instruction
else
elna_instruction_list_concatenate(last_instruction, current_instruction)
end;
last_instruction := current_instruction;
parameter_index := parameter_index + 1; parameter_index := parameter_index + 1;
goto elna_rtl_parameters_loop goto elna_rtl_parameters_loop
@@ -3640,19 +3491,18 @@ end;
proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaTacProcedure); proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaTacProcedure);
var var
result: ^ElnaRtlProcedure; result: ^ElnaRtlProcedure;
body: ^ElnaRtlInstruction;
parameters: ^ElnaRtlInstruction;
begin begin
result := malloc(#size(ElnaRtlProcedure)); result := malloc(#size(ElnaRtlProcedure));
elna_list_initialize(@result^.body);
result^.next := nil; result^.next := nil;
result^.name := tac_declaration^.name; result^.name := tac_declaration^.name;
result^.length := tac_declaration^.length; 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); result^.variable_map := elna_rtl_symbol_table(tac_declaration^.symbol_table);
body := elna_rtl_instructions(tac_declaration^.body, result^.variable_map); elna_rtl_instructions(@result^.body, tac_declaration^.body.first, result^.variable_map);
result^.body := elna_instruction_list_concatenate(parameters, body);
return result return result
end; end;