Move register allocation into the allocation pass

This commit is contained in:
2026-03-07 22:50:13 +01:00
parent 8678a09694
commit aab7e42260

View File

@@ -477,7 +477,7 @@ type
jump_if_not_zero, jump_if_not_zero,
label, label,
_return, _return,
noop nop
); );
ElnaTacKind = (list, immediate, symbol, pseudo); ElnaTacKind = (list, immediate, symbol, pseudo);
ElnaTacOperand = record ElnaTacOperand = record
@@ -534,7 +534,7 @@ type
label, label,
allocate_stack, allocate_stack,
ret, ret,
noop nop
); );
ElnaRtlKind = (register, immediate, symbol, pseudo, offset, pseudo_mem); ElnaRtlKind = (register, immediate, symbol, pseudo, offset, pseudo_mem);
ElnaRtlOperand = record ElnaRtlOperand = record
@@ -816,9 +816,9 @@ var
temporary_info: ^ElnaSymbolTemporaryInfo; temporary_info: ^ElnaSymbolTemporaryInfo;
begin begin
pseudo_counter := pseudo_counter + 1; pseudo_counter := pseudo_counter + 1;
buffer := malloc(6); buffer := malloc(7);
sprintf(buffer, "$%i\0", pseudo_counter); sprintf(buffer, "$a%i\0", pseudo_counter);
operand_type^ := ElnaTacKind.pseudo; operand_type^ := ElnaTacKind.pseudo;
operand_value^ := buffer; operand_value^ := buffer;
@@ -866,168 +866,221 @@ begin
this^.operands[n].length := operand_length this^.operands[n].length := operand_length
end; end;
proc elna_rtl_load_operand_value(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, operand_number: Word, into: Word); (**
* Loads or moves the value from a TAC operand into the given register.
*)
proc elna_rtl_load_operand_value(instructions: ^ElnaList, operand: ^ElnaTacOperand,
into: ElnaRtlRegister, variable_map: ^ElnaSymbolTable);
var var
instruction: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
operand_value: Word; pseudo_symbol: ^ElnaRtlInfo;
operand_length: Word;
operand_type: Word;
begin begin
operand_type := tac_instruction^.operands[operand_number].kind; if operand^.kind = ElnaTacKind.immediate then
operand_value := tac_instruction^.operands[operand_number].value;
operand_length := tac_instruction^.operands[operand_number].length;
if operand_type = ElnaTacKind.immediate then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.li); instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); 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, 2, ElnaRtlKind.immediate, operand^.value, operand^.length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif operand_type = ElnaTacKind.symbol then elsif operand^.kind = ElnaTacKind.symbol then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); 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, 2, ElnaRtlKind.symbol, operand^.value, operand^.length);
elna_list_append(instructions, instruction); elna_list_append(instructions, instruction);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); 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, 2, ElnaRtlKind.offset, into, 0);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif operand_type = ElnaTacKind.pseudo then elsif operand^.kind = ElnaTacKind.pseudo 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_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)
else
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move); instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0); 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, 2, ElnaRtlKind.pseudo, operand^.value, operand^.length)
end;
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end end
end; end;
proc elna_rtl_binary_operands(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction); proc elna_rtl_operand_value(instructions: ^ElnaList, tac_operand: ^ElnaTacOperand, variable_map: ^ElnaSymbolTable, rtl_operand: ^ElnaRtlOperand);
begin
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_arithmetic(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, operation: Word);
var var
instruction: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
begin begin
elna_rtl_binary_operands(instructions, tac_instruction); rtl_operand^.kind := ElnaRtlKind.pseudo;
instruction := elna_rtl_instruction_create(operation); if tac_operand^.kind = ElnaTacKind.immediate then
elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map);
elna_rtl_copy_operand(tac_instruction, 1, instruction); instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0); elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, ElnaRtlRegister.t3, 0); elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, tac_operand^.value, tac_operand^.length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end; elsif tac_operand^.kind = ElnaTacKind.symbol then
elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map);
proc elna_rtl_binary_equality(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, instruction_kind: Word); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
var elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length);
instruction: ^ElnaRtlInstruction; elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, tac_operand^.value, tac_operand^.length);
begin
elna_rtl_binary_operands(instructions, tac_instruction);
instruction := elna_rtl_instruction_create(ElnaRtlOperator._xor);
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); elna_list_append(instructions, instruction);
instruction := elna_rtl_instruction_create(instruction_kind); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_copy_operand(tac_instruction, 1, instruction); elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t2, 0); elna_rtl_instruction_set_operand(instruction, 2, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif tac_operand^.kind = ElnaTacKind.pseudo then
pseudo_symbol := elna_symbol_table_lookup(variable_map, tac_operand^.value, tac_operand^.length);
if pseudo_symbol = nil then
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_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_list_append(instructions, instruction)
else
rtl_operand^.value := tac_operand^.value;
rtl_operand^.length := tac_operand^.length
end
end
end;
proc elna_rtl_binary_arithmetic(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction,
operation: ElnaRtlOperator, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction;
var
result: ^ElnaRtlInstruction;
rtl_operand: ElnaRtlOperand;
begin
result := elna_rtl_instruction_create(operation);
elna_rtl_copy_operand(instructions, @tac_instruction^.operands[1], 1, result, variable_map);
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_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_list_append(instructions, result);
return result
end;
proc elna_rtl_binary_equality(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction,
instruction_kind: ElnaRtlOperator, variable_map: ^ElnaSymbolTable);
var
instruction: ^ElnaRtlInstruction;
target_operand: ^ElnaRtlOperand;
begin
instruction := elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator._xor, variable_map);
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_list_append(instructions, instruction)
end;
proc elna_rtl_set_less_than(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction,
lhs: Word, rhs: Word, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction;
var
slt_instruction: ^ElnaRtlInstruction;
rtl_operand: ElnaRtlOperand;
begin
slt_instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt);
elna_rtl_copy_operand(instructions, @tac_instruction^.operands[1], 1, slt_instruction, variable_map);
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_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_list_append(instructions, slt_instruction);
return slt_instruction
end; end;
proc elna_rtl_binary_comparison(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, proc elna_rtl_binary_comparison(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction,
lhs: ElnaRtlRegister, rhs: ElnaRtlRegister); lhs: Word, rhs: Word, variable_map: ^ElnaSymbolTable);
var var
instruction: ^ElnaRtlInstruction; slt_instruction: ^ElnaRtlInstruction;
xor_instruction: ^ElnaRtlInstruction;
rtl_operand: ElnaRtlOperand;
begin begin
elna_rtl_binary_operands(instructions, tac_instruction); slt_instruction := elna_rtl_set_less_than(instructions, tac_instruction, lhs, rhs, variable_map);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.slt); xor_instruction := elna_rtl_instruction_create(ElnaRtlOperator.xori);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t2, 0); elna_rtl_instruction_set_operand(xor_instruction, 1, slt_instruction^.operands[1].kind,
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, lhs, 0); slt_instruction^.operands[1].value, slt_instruction^.operands[1].length);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.register, rhs, 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);
elna_list_append(instructions, instruction); elna_list_append(instructions, xor_instruction)
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);
elna_list_append(instructions, instruction)
end; end;
proc elna_rtl_copy_operand(tac_instruction: ^ElnaTacInstruction, number: Word, rtl_instruction: Word); proc elna_rtl_copy_operand(instructions: ^ElnaList, tac_operand: ^ElnaTacOperand, number: Word,
rtl_instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var var
operand_length: Word; operand_length: Word;
operand_type: Word;
operand_value: Word; operand_value: Word;
pseudo_symbol: ^ElnaRtlInfo;
instruction: ^ElnaRtlInstruction;
begin begin
operand_type := tac_instruction^.operands[number].kind; operand_value := tac_operand^.value;
operand_value := tac_instruction^.operands[number].value; operand_length := tac_operand^.length;
operand_length := tac_instruction^.operands[number].length;
if operand_type = ElnaTacKind.immediate then if tac_operand^.kind = ElnaTacKind.immediate then
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.immediate, operand_value, operand_length) elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.immediate, operand_value, operand_length)
elsif operand_type = ElnaTacKind.symbol then elsif tac_operand^.kind = ElnaTacKind.symbol then
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.symbol, operand_value, operand_length) elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.symbol, operand_value, operand_length)
elsif operand_type = ElnaTacKind.pseudo then elsif tac_operand^.kind = ElnaTacKind.pseudo then
pseudo_symbol := elna_symbol_table_lookup(variable_map, operand_value, operand_length);
if pseudo_symbol = nil then
pseudo_symbol := elna_rtl_generate_pseudo(@operand_value, @operand_length, variable_map);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, operand_value, operand_length);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, tac_operand^.value, tac_operand^.length);
elna_list_append(instructions, instruction)
end;
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.pseudo, operand_value, operand_length) elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.pseudo, operand_value, operand_length)
end end
end; end;
proc elna_rtl_conditional_jump(instructions: ^ElnaList, tac_instruction: Word, condition: Word); proc elna_rtl_conditional_jump(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction,
condition: ElnaRtlOperator, variable_map: ^ElnaSymbolTable);
var var
instruction: Word; instruction: ^ElnaRtlInstruction;
rtl_operand: ElnaRtlOperand;
begin begin
instruction := elna_rtl_instruction_create(condition); instruction := elna_rtl_instruction_create(condition);
elna_rtl_copy_operand(tac_instruction, 1, instruction); elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand);
elna_rtl_copy_operand(tac_instruction, 2, instruction); 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_instruction^.operands[2].value, tac_instruction^.operands[2].length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end; end;
proc elna_rtl_unary(instructions: ^ElnaList, tac_instruction: Word, rtl_operator: Word); proc elna_rtl_unary(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, rtl_operator: ElnaRtlOperator, variable_map: ^ElnaSymbolTable);
var var
instruction: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
rtl_operand: ElnaRtlOperand;
begin begin
elna_rtl_load_operand_value(instructions, tac_instruction, 2, ElnaRtlRegister.t0); elna_rtl_operand_value(instructions, @tac_instruction^.operands[2], variable_map, @rtl_operand);
instruction := elna_rtl_instruction_create(rtl_operator); instruction := elna_rtl_instruction_create(rtl_operator);
elna_rtl_copy_operand(tac_instruction, 1, instructions^.first); elna_rtl_copy_operand(instructions, @tac_instruction^.operands[1], 1, instruction, variable_map);
elna_rtl_instruction_set_operand(instructions^.first, 2, ElnaRtlKind.register, ElnaRtlRegister.t0); elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length);
elna_list_append(instructions, instruction)
end;
proc elna_rtl_call_parameter(instructions: ^ElnaList, current_argument: ^ElnaTacOperand, into: ElnaRtlRegister);
var
instruction: ^ElnaRtlInstruction;
begin
if current_argument^.kind = ElnaTacKind.pseudo then
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, ElnaTacKind.pseudo,
current_argument^.value, current_argument^.length)
elsif current_argument^.kind = ElnaTacKind.immediate 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, ElnaTacKind.immediate,
current_argument^.value, current_argument^.length)
elsif current_argument^.kind = ElnaTacKind.symbol 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,
current_argument^.value, current_argument^.length);
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_list_append(instructions, instruction)
end;
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end; end;
@@ -1048,14 +1101,15 @@ begin
if argument_count > 0 then if argument_count > 0 then
argument_count := argument_count - 1; argument_count := argument_count - 1;
elna_rtl_call_parameter(instructions, current_argument, ElnaRtlRegister.a0 + current_register); elna_rtl_load_operand_value(instructions, current_argument, ElnaRtlRegister.a0 + current_register, variable_map);
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;
instruction := elna_rtl_instruction_create(ElnaRtlOperator.jal); instruction := elna_rtl_instruction_create(ElnaRtlOperator.jal);
elna_rtl_copy_operand(tac_instruction, 1, instruction); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.symbol,
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
elna_list_append(instructions, instruction); elna_list_append(instructions, instruction);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move); instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
@@ -1065,31 +1119,30 @@ begin
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end; end;
proc elna_rtl_store(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction); proc elna_rtl_store(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var var
instruction: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
rtl_operand: ElnaRtlOperand;
begin begin
elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.t0); elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0); elna_rtl_instruction_set_operand(instruction, 1, rtl_operand.kind, rtl_operand.value, rtl_operand.length);
if tac_instruction^.operands[2].kind = ElnaTacKind.pseudo then
elna_rtl_instruction_set_operand(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;
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end; end;
proc elna_rtl_load(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction); proc elna_rtl_load(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var var
instruction: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
rtl_operand: ElnaRtlOperand;
begin begin
elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.t0); elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); 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, elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length);
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);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end; end;
@@ -1097,74 +1150,80 @@ end;
proc elna_rtl_instruction(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); proc elna_rtl_instruction(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable);
var var
instruction: ^ElnaRtlInstruction; instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
rtl_operand: ElnaRtlOperand;
begin begin
if tac_instruction^.operator = ElnaTacOperator.get_address then if tac_instruction^.operator = ElnaTacOperator.get_address then
pseudo_symbol := elna_symbol_table_lookup(variable_map,
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_copy_operand(tac_instruction, 1, instruction); elna_rtl_copy_operand(instructions, @tac_instruction^.operands[1], 1, instruction, variable_map);
elna_rtl_copy_operand(tac_instruction, 2, instruction); if pseudo_symbol = nil then
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol,
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length)
else
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo,
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length)
end;
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.add then elsif tac_instruction^.operator = ElnaTacOperator.add then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.add) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.add, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.load then elsif tac_instruction^.operator = ElnaTacOperator.load then
elna_rtl_load(instructions, tac_instruction) elna_rtl_load(instructions, tac_instruction, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.store then elsif tac_instruction^.operator = ElnaTacOperator.store then
elna_rtl_store(instructions, tac_instruction) elna_rtl_store(instructions, tac_instruction, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.proc_call then elsif tac_instruction^.operator = ElnaTacOperator.proc_call then
elna_rtl_call(instructions, tac_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
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.sub) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.sub, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.multiply then elsif tac_instruction^.operator = ElnaTacOperator.multiply then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.mul) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.mul, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.divide then elsif tac_instruction^.operator = ElnaTacOperator.divide then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.div) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.div, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.remainder then elsif tac_instruction^.operator = ElnaTacOperator.remainder then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.rem) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.rem, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator._xor then elsif tac_instruction^.operator = ElnaTacOperator._xor then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator._xor) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator._xor, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator._or then elsif tac_instruction^.operator = ElnaTacOperator._or then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator._or) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator._or, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.and then elsif tac_instruction^.operator = ElnaTacOperator.and then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.and) elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.and, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.less_than then elsif tac_instruction^.operator = ElnaTacOperator.less_than then
elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.slt) elna_rtl_set_less_than(instructions, tac_instruction, 2, 3, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.greater_than then elsif tac_instruction^.operator = ElnaTacOperator.greater_than then
elna_rtl_binary_operands(instructions, tac_instruction); elna_rtl_set_less_than(instructions, tac_instruction, 3, 2, variable_map)
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 elsif tac_instruction^.operator = ElnaTacOperator.less_or_equal then
elna_rtl_binary_comparison(instructions, tac_instruction, ElnaRtlRegister.t3, ElnaRtlRegister.t2) elna_rtl_binary_comparison(instructions, tac_instruction, 3, 2, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.greater_or_equal then elsif tac_instruction^.operator = ElnaTacOperator.greater_or_equal then
elna_rtl_binary_comparison(instructions, tac_instruction, ElnaRtlRegister.t2, ElnaRtlRegister.t3) elna_rtl_binary_comparison(instructions, tac_instruction, 2, 3, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.equal then elsif tac_instruction^.operator = ElnaTacOperator.equal then
elna_rtl_binary_equality(instructions, tac_instruction, ElnaRtlOperator.seqz) elna_rtl_binary_equality(instructions, tac_instruction, ElnaRtlOperator.seqz, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.not_equal then elsif tac_instruction^.operator = ElnaTacOperator.not_equal then
elna_rtl_binary_equality(instructions, tac_instruction, ElnaRtlOperator.snez) elna_rtl_binary_equality(instructions, tac_instruction, ElnaRtlOperator.snez, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.negate then elsif tac_instruction^.operator = ElnaTacOperator.negate then
elna_rtl_unary(instructions, tac_instruction, ElnaRtlOperator.neg) elna_rtl_unary(instructions, tac_instruction, ElnaRtlOperator.neg, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.complement then elsif tac_instruction^.operator = ElnaTacOperator.complement then
elna_rtl_unary(instructions, tac_instruction, ElnaRtlOperator.not) elna_rtl_unary(instructions, tac_instruction, ElnaRtlOperator.not, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.jump then elsif tac_instruction^.operator = ElnaTacOperator.jump then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.j); instruction := elna_rtl_instruction_create(ElnaRtlOperator.j);
elna_rtl_copy_operand(tac_instruction, 1, instruction); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.symbol,
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.jump_if_zero then elsif tac_instruction^.operator = ElnaTacOperator.jump_if_zero then
elna_rtl_conditional_jump(instructions, tac_instruction, ElnaRtlOperator.beqz) elna_rtl_conditional_jump(instructions, tac_instruction, ElnaRtlOperator.beqz, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.jump_if_not_zero then elsif tac_instruction^.operator = ElnaTacOperator.jump_if_not_zero then
elna_rtl_conditional_jump(instructions, tac_instruction, ElnaRtlOperator.bnez) elna_rtl_conditional_jump(instructions, tac_instruction, ElnaRtlOperator.bnez, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator._return then elsif tac_instruction^.operator = ElnaTacOperator._return then
elna_rtl_load_operand_value(instructions, tac_instruction, 1, ElnaRtlRegister.a0) elna_rtl_load_operand_value(instructions, @tac_instruction^.operands[1], ElnaRtlRegister.a0, variable_map)
elsif tac_instruction^.operator = ElnaTacOperator.label then elsif tac_instruction^.operator = ElnaTacOperator.label then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.label); instruction := elna_rtl_instruction_create(ElnaRtlOperator.label);
elna_rtl_copy_operand(tac_instruction, 1, instruction); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.symbol,
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
elna_list_append(instructions, 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
elna_rtl_load_operand_value(instructions, tac_instruction, 2, ElnaRtlRegister.t4); elna_rtl_load_operand_value(instructions, @tac_instruction^.operands[2], ElnaRtlRegister.t4, variable_map);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move); instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_tac_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, elna_tac_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo,
@@ -1172,10 +1231,8 @@ begin
elna_tac_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t4, 0); elna_tac_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.t4, 0);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end end
elsif tac_instruction^.operator = ElnaTacOperator.noop then elsif tac_instruction^.operator = ElnaTacOperator.nop then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.noop); instruction := elna_rtl_instruction_create(ElnaRtlOperator.nop);
elna_rtl_copy_operand(tac_instruction, 1, instruction);
elna_rtl_copy_operand(tac_instruction, 2, instruction);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end end
end; end;
@@ -1321,7 +1378,8 @@ end;
* to be a register, but is not a register, then this procedure rewrites it * to be a register, but is not a register, then this procedure rewrites it
* to a temporary register and preserves its value in the following instruction. * to a temporary register and preserves its value in the following instruction.
*) *)
proc elna_alloc_operation_target(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable); proc elna_alloc_operation_target(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction,
variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction;
var var
pseudo_symbol: ^ElnaRtlInfo; pseudo_symbol: ^ElnaRtlInfo;
store_instruction: ^ElnaRtlInstruction; store_instruction: ^ElnaRtlInstruction;
@@ -1335,8 +1393,10 @@ begin
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter); elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, 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);
elna_list_insert(instructions, instruction, store_instruction) elna_list_insert(instructions, instruction, store_instruction);
end instruction := store_instruction
end;
return instruction
end; end;
proc elna_alloc_load_address(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable); proc elna_alloc_load_address(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
@@ -1358,15 +1418,17 @@ end;
proc elna_alloc_store(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable); proc elna_alloc_store(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var var
old_instruction: ^ElnaRtlInstruction; store_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo; pseudo_symbol: ^ElnaRtlInfo;
begin begin
if instruction^.operands[2].kind = ElnaRtlKind.pseudo then instruction := elna_alloc_operand(instructions, instruction, 1, ElnaRtlRegister.t0, variable_map);
old_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
elna_rtl_instruction_set_operand(old_instruction, 1, instruction^.operands[1].kind, if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
store_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
elna_rtl_instruction_set_operand(store_instruction, 1, instruction^.operands[1].kind,
instruction^.operands[1].value, instruction^.operands[1].length); instruction^.operands[1].value, instruction^.operands[1].length);
elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t1, 0); elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t1, 0);
pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length, pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
variable_map); variable_map);
@@ -1374,8 +1436,10 @@ begin
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0); 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, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
elna_list_insert(instructions, instruction, old_instruction) elna_list_insert(instructions, instruction, store_instruction);
end instruction := store_instruction
end;
return instruction
end; end;
proc elna_alloc_load(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable); proc elna_alloc_load(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
@@ -1383,17 +1447,23 @@ var
new_instruction: ^ElnaRtlInstruction; new_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo; pseudo_symbol: ^ElnaRtlInfo;
begin begin
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length, pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value,
variable_map); instruction^.operands[2].length, variable_map);
new_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); new_instruction := malloc(#size(ElnaRtlInstruction));
memcpy(new_instruction, instruction, #size(ElnaRtlInstruction));
new_instruction^.next := nil;
elna_rtl_instruction_set_operand(new_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0); elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t1, 0);
elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
instruction^.operator := ElnaRtlOperator.lw;
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
elna_list_insert(instructions, instruction, new_instruction) elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
end elna_list_insert(instructions, instruction, new_instruction);
instruction := new_instruction
end;
return elna_alloc_operation_target(instructions, instruction, variable_map)
end; end;
proc elna_alloc_move(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable); proc elna_alloc_move(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
@@ -1416,7 +1486,51 @@ begin
end end
end; end;
proc elna_alloc_instruction(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable); proc elna_alloc_operand(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction,
number: Word, target: ElnaRtlRegister, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction;
var
main_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
begin
if instruction^.operands[number].kind = ElnaRtlKind.pseudo then
pseudo_symbol := elna_alloc_variable(instruction^.operands[number].value,
instruction^.operands[number].length, variable_map);
main_instruction := malloc(#size(ElnaRtlInstruction));
memcpy(main_instruction, instruction, #size(ElnaRtlInstruction));
main_instruction^.next := nil;
elna_rtl_instruction_set_operand(main_instruction, number, ElnaRtlKind.register, target, 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_list_insert(instructions, instruction, main_instruction);
instruction := main_instruction
end;
return instruction
end;
proc elna_alloc_binary(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction;
var
new_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
begin
instruction := elna_alloc_operand(instructions, instruction, 2, ElnaRtlRegister.t2, variable_map);
instruction := elna_alloc_operand(instructions, instruction, 3, ElnaRtlRegister.t3, variable_map);
return elna_alloc_operation_target(instructions, instruction, variable_map)
end;
proc elna_alloc_unary(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction;
var
new_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
begin
instruction := elna_alloc_operand(instructions, instruction, 2, ElnaRtlRegister.t2, variable_map);
return elna_alloc_operation_target(instructions, instruction, variable_map)
end;
proc elna_alloc_instruction(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInstruction;
var var
pseudo_symbol: ^ElnaRtlInfo; pseudo_symbol: ^ElnaRtlInfo;
new_instruction: ^ElnaRtlInstruction; new_instruction: ^ElnaRtlInstruction;
@@ -1426,25 +1540,25 @@ begin
elsif instruction^.operator = ElnaRtlOperator.la then elsif instruction^.operator = ElnaRtlOperator.la then
elna_alloc_load_address(instructions, instruction, variable_map) elna_alloc_load_address(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.lw then elsif instruction^.operator = ElnaRtlOperator.lw then
elna_alloc_load(instructions, instruction, variable_map) instruction := elna_alloc_load(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.sw then elsif instruction^.operator = ElnaRtlOperator.sw then
elna_alloc_store(instructions, instruction, variable_map) instruction := elna_alloc_store(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator._or then elsif instruction^.operator = ElnaRtlOperator._or then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.and then elsif instruction^.operator = ElnaRtlOperator.and then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.mul then elsif instruction^.operator = ElnaRtlOperator.mul then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.sub then elsif instruction^.operator = ElnaRtlOperator.sub then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.add then elsif instruction^.operator = ElnaRtlOperator.add then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator._xor then elsif instruction^.operator = ElnaRtlOperator._xor then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.rem then elsif instruction^.operator = ElnaRtlOperator.rem then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.slt then elsif instruction^.operator = ElnaRtlOperator.slt then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.beqz then elsif instruction^.operator = ElnaRtlOperator.beqz then
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
new_instruction := elna_rtl_instruction_create(ElnaRtlOperator.beqz); new_instruction := elna_rtl_instruction_create(ElnaRtlOperator.beqz);
@@ -1462,12 +1576,17 @@ begin
elna_list_insert(instructions, instruction, new_instruction) elna_list_insert(instructions, instruction, new_instruction)
end end
elsif instruction^.operator = ElnaRtlOperator.seqz then elsif instruction^.operator = ElnaRtlOperator.seqz then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_unary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.snez then elsif instruction^.operator = ElnaRtlOperator.snez then
elna_alloc_operation_target(instructions, instruction, variable_map) instruction := elna_alloc_unary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.xori then elsif instruction^.operator = ElnaRtlOperator.xori then
instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.addi then
instruction := elna_alloc_binary(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.li then
elna_alloc_operation_target(instructions, instruction, variable_map) elna_alloc_operation_target(instructions, instruction, variable_map)
end end;
return instruction^.next
end; end;
proc elna_riscv_instruction(instruction: ^ElnaRtlInstruction); proc elna_riscv_instruction(instruction: ^ElnaRtlInstruction);
@@ -1494,15 +1613,7 @@ begin
(* Write the epilogue. *) (* Write the epilogue. *)
printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0", operand_value + 4, operand_value, operand_value + 8); printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0", operand_value + 4, operand_value, operand_value + 8);
fflush(nil) fflush(nil)
elsif instruction^.operator = ElnaRtlOperator.noop then elsif instruction^.operator = ElnaRtlOperator.nop then
operand_value := instruction^.operands[2].value;
if operand_value = 0 then
printf("# Debug start\n\0");
else
printf("# Debug end\n\0");
end;
fflush(nil)
else else
argument_count := elna_riscv_instruction_name(instruction^.operator) argument_count := elna_riscv_instruction_name(instruction^.operator)
end; end;
@@ -1541,8 +1652,8 @@ begin
.elna_alloc_instructions_start; .elna_alloc_instructions_start;
if instruction <> nil then if instruction <> nil then
elna_alloc_instruction(instructions, instruction, variable_map); instruction := elna_alloc_instruction(instructions, instruction, variable_map);
instruction := instruction^.next;
goto elna_alloc_instructions_start goto elna_alloc_instructions_start
end end
end; end;
@@ -2551,28 +2662,18 @@ begin
instruction := elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand); instruction := elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand);
if assignee.kind = ElnaTacKind.pseudo then if assignee.kind = ElnaTacKind.pseudo then
if is_address 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); instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
if is_address then
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table);
(* Save the assignee address on the stack. *)
elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length);
elna_list_append(instructions, instruction);
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, operand_type, operand_value, operand_length);
elna_list_append(instructions, instruction)
else
elna_tac_instruction_set_operand(instruction, 1, assignee.kind, assignee.value, assignee.length); 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, 2, assignment_operand.kind, assignment_operand.value, assignment_operand.length)
end;
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end
else else
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table); elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table);
@@ -3429,6 +3530,32 @@ begin
return lhs or rhs return lhs or rhs
end; end;
proc elna_rtl_generate_pseudo(operand_value: Word, operand_length: Word, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInfo;
var
pseudo_symbol: ^ElnaRtlInfo;
pseudo_type: ^ElnaRtlTypeWord;
buffer: Word;
begin
pseudo_counter := pseudo_counter + 1;
pseudo_symbol := malloc(#size(ElnaRtlInfo));
buffer := malloc(7);
sprintf(buffer, "$b%i\0", pseudo_counter);
pseudo_symbol^.allocated := false;
pseudo_type := malloc(#size(ElnaRtlTypeWord));
pseudo_type^.kind := ElnaRtlTypeKind.long_word;
pseudo_type^.size := 4;
operand_value^ := buffer;
operand_length^ := strlen(buffer);
pseudo_symbol^.rtl_type := pseudo_type;
elna_symbol_table_enter(variable_map, buffer, operand_length^, pseudo_symbol);
return pseudo_symbol
end;
proc elna_rtl_symbol_table(symbol_table: ^ElnaSymbolTable); proc elna_rtl_symbol_table(symbol_table: ^ElnaSymbolTable);
var var
variable_map: ^ElnaSymbolTable; variable_map: ^ElnaSymbolTable;
@@ -3487,6 +3614,7 @@ begin
result^.name := tac_declaration^.name; result^.name := tac_declaration^.name;
result^.length := tac_declaration^.length; result^.length := tac_declaration^.length;
pseudo_counter := 0;
elna_rtl_parameters(@result^.body, 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);
@@ -4383,38 +4511,21 @@ proc elna_lexer_classifications();
var var
code: Word; code: Word;
begin begin
code := 1;
(* Set everything by default to invalid. *)
.elna_lexer_classifications_invalid;
classification[code] := ElnaLexerClass.invalid;
code := code + 1;
if code < 129 then
goto elna_lexer_classifications_invalid
end;
classification[1] := ElnaLexerClass.eof; classification[1] := ElnaLexerClass.eof;
classification[2] := ElnaLexerClass.invalid;
classification[3] := ElnaLexerClass.invalid;
classification[4] := ElnaLexerClass.invalid;
classification[5] := ElnaLexerClass.invalid;
classification[6] := ElnaLexerClass.invalid;
classification[7] := ElnaLexerClass.invalid;
classification[8] := ElnaLexerClass.invalid;
classification[9] := ElnaLexerClass.invalid;
classification[10] := ElnaLexerClass.space; classification[10] := ElnaLexerClass.space;
classification[11] := ElnaLexerClass.space; classification[11] := ElnaLexerClass.space;
classification[12] := ElnaLexerClass.invalid;
classification[13] := ElnaLexerClass.invalid;
classification[14] := ElnaLexerClass.space; classification[14] := ElnaLexerClass.space;
classification[15] := ElnaLexerClass.invalid;
classification[16] := ElnaLexerClass.invalid;
classification[17] := ElnaLexerClass.invalid;
classification[18] := ElnaLexerClass.invalid;
classification[19] := ElnaLexerClass.invalid;
classification[20] := ElnaLexerClass.invalid;
classification[21] := ElnaLexerClass.invalid;
classification[22] := ElnaLexerClass.invalid;
classification[23] := ElnaLexerClass.invalid;
classification[24] := ElnaLexerClass.invalid;
classification[25] := ElnaLexerClass.invalid;
classification[26] := ElnaLexerClass.invalid;
classification[27] := ElnaLexerClass.invalid;
classification[28] := ElnaLexerClass.invalid;
classification[29] := ElnaLexerClass.invalid;
classification[30] := ElnaLexerClass.invalid;
classification[31] := ElnaLexerClass.invalid;
classification[32] := ElnaLexerClass.invalid;
classification[33] := ElnaLexerClass.space; classification[33] := ElnaLexerClass.space;
classification[34] := ElnaLexerClass.single; classification[34] := ElnaLexerClass.single;
classification[35] := ElnaLexerClass.double_quote; classification[35] := ElnaLexerClass.double_quote;
@@ -4510,17 +4621,14 @@ begin
classification[125] := ElnaLexerClass.single; classification[125] := ElnaLexerClass.single;
classification[126] := ElnaLexerClass.other; classification[126] := ElnaLexerClass.other;
classification[127] := ElnaLexerClass.single; classification[127] := ElnaLexerClass.single;
classification[128] := ElnaLexerClass.invalid;
code := 129;
(* Set the remaining 129 - 256 bytes to transitionClassOther. *) (* Set the remaining 129 - 256 bytes to transitionClassOther. *)
.create_classification_loop; .elna_lexer_classifications_other;
classification[code] := ElnaLexerClass.other; classification[code] := ElnaLexerClass.other;
code := code + 1; code := code + 1;
if code < 257 then if code < 257 then
goto create_classification_loop goto elna_lexer_classifications_other
end end
end; end;