Handle TAC global and local variables

This commit is contained in:
2026-03-14 21:39:53 +01:00
parent cb6d970fdf
commit 953447dc23

View File

@@ -500,7 +500,7 @@ type
_return,
nop
);
ElnaTacKind = (list, immediate, symbol, pseudo);
ElnaTacKind = (list, label, constant, variable);
ElnaTacOperand = record
kind: ElnaTacKind;
value: Word;
@@ -617,16 +617,15 @@ type
);
ElnaRtlTypeKind = (long_word, byte_array);
ElnaRtlType = record
kind: ElnaRtlTypeKind;
size: Word
kind: ElnaRtlTypeKind
end;
ElnaRtlTypeWord = record
kind: ElnaRtlTypeKind;
size: Word
kind: ElnaRtlTypeKind
end;
ElnaRtlTypeByteArray = record
kind: ElnaRtlTypeKind;
size: Word
size: Word;
alignment: Word
end;
ElnaRtlInfo = record
counter: Word;
@@ -841,7 +840,7 @@ begin
sprintf(buffer, "$a%i\0", pseudo_counter);
operand_type^ := ElnaTacKind.pseudo;
operand_type^ := ElnaTacKind.variable;
operand_value^ := buffer;
operand_length^ := strlen(buffer);
@@ -896,22 +895,12 @@ var
instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
begin
if operand^.kind = ElnaTacKind.immediate then
if operand^.kind = ElnaTacKind.constant then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, into, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, operand^.value, operand^.length);
elna_list_append(instructions, instruction)
elsif operand^.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, 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);
elna_list_append(instructions, instruction)
elsif operand^.kind = ElnaTacKind.pseudo then
elsif operand^.kind = ElnaTacKind.variable then
pseudo_symbol := elna_symbol_table_lookup(variable_map, operand^.value, operand^.length);
if pseudo_symbol = nil then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.la);
@@ -937,26 +926,14 @@ var
pseudo_symbol: ^ElnaRtlInfo;
begin
rtl_operand^.kind := ElnaRtlKind.pseudo;
if tac_operand^.kind = ElnaTacKind.immediate then
if tac_operand^.kind = ElnaTacKind.constant then
elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(instruction, 1, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.immediate, tac_operand^.value, tac_operand^.length);
elna_list_append(instructions, instruction)
elsif tac_operand^.kind = ElnaTacKind.symbol 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)
elsif tac_operand^.kind = ElnaTacKind.pseudo then
elsif tac_operand^.kind = ElnaTacKind.variable 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);
@@ -1060,11 +1037,9 @@ begin
operand_value := tac_operand^.value;
operand_length := tac_operand^.length;
if tac_operand^.kind = ElnaTacKind.immediate then
if tac_operand^.kind = ElnaTacKind.constant then
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.immediate, operand_value, operand_length)
elsif tac_operand^.kind = ElnaTacKind.symbol then
elna_rtl_instruction_set_operand(rtl_instruction, number, ElnaRtlKind.symbol, operand_value, operand_length)
elsif tac_operand^.kind = ElnaTacKind.pseudo then
elsif tac_operand^.kind = ElnaTacKind.variable 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);
@@ -1243,7 +1218,7 @@ begin
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
elna_list_append(instructions, instruction)
elsif tac_instruction^.operator = ElnaTacOperator.copy then
if tac_instruction^.operands[1].kind = ElnaTacKind.pseudo then
if tac_instruction^.operands[1].kind = ElnaTacKind.variable then
elna_rtl_load_operand_value(instructions, @tac_instruction^.operands[2], ElnaRtlRegister.t4, variable_map);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
@@ -1254,6 +1229,10 @@ begin
end
elsif tac_instruction^.operator = ElnaTacOperator.nop then
instruction := elna_rtl_instruction_create(ElnaRtlOperator.nop);
elna_tac_instruction_set_operand(instruction, 1, tac_instruction^.operands[1].kind,
tac_instruction^.operands[1].value, tac_instruction^.operands[1].length);
elna_tac_instruction_set_operand(instruction, 2, tac_instruction^.operands[2].kind,
tac_instruction^.operands[2].value, tac_instruction^.operands[2].length);
elna_list_append(instructions, instruction)
end
end;
@@ -1263,7 +1242,7 @@ var
result: Word;
begin
result := elna_tac_instruction_create(ElnaTacOperator.label);
elna_tac_instruction_set_operand(result, 1, ElnaTacKind.symbol, counter, length);
elna_tac_instruction_set_operand(result, 1, ElnaTacKind.label, counter, length);
elna_list_append(instructions, result)
end;
@@ -1383,14 +1362,25 @@ end;
proc elna_alloc_variable(operand_value: Word, operand_length: Word, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
pseudo_type: ^ElnaRtlTypeByteArray;
begin
pseudo_symbol := elna_symbol_table_lookup(variable_map, operand_value, operand_length);
if pseudo_symbol = nil then
goto elna_alloc_variable_end
end;
if pseudo_symbol^.allocated = false then
pseudo_symbol^.allocated := true;
pseudo_symbol^.counter := temporary_variable_counter;
temporary_variable_counter := temporary_variable_counter + pseudo_symbol^.rtl_type^.size
if pseudo_symbol^.rtl_type^.kind = ElnaRtlTypeKind.byte_array then
pseudo_type := pseudo_symbol^.rtl_type;
temporary_variable_counter := temporary_variable_counter + pseudo_type^.size
else
temporary_variable_counter := temporary_variable_counter + 4
end
end;
.elna_alloc_variable_end;
return pseudo_symbol
end;
@@ -1496,9 +1486,16 @@ begin
variable_map);
instruction^.operator = ElnaRtlOperator.sw;
elna_rtl_instruction_set_operand(instruction, 1, instruction^.operands[2].kind,
instruction^.operands[2].value, instruction^.operands[2].length);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter)
if pseudo_symbol = nil then
elna_rtl_instruction_set_operand(instruction, 1, instruction^.operands[2].kind,
instruction^.operands[2].value, instruction^.operands[2].length);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol,
instruction^.operands[1].value, instruction^.operands[1].length)
else
elna_rtl_instruction_set_operand(instruction, 1, instruction^.operands[2].kind,
instruction^.operands[2].value, instruction^.operands[2].length);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter)
end;
elsif instruction^.operands[2].kind = ElnaRtlKind.pseudo then
pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
variable_map);
@@ -1637,6 +1634,12 @@ begin
printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0", operand_value - 4, operand_value - 8, operand_value);
fflush(nil)
elsif instruction^.operator = ElnaRtlOperator.nop then
operand_value := instruction^.operands[1].value;
printf("\n# copy (%i %.*s) (%i %.*s)\n\0", instruction^.operands[1].kind,
instruction^.operands[1].length, operand_value,
instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value);
fflush(nil)
else
argument_count := elna_riscv_instruction_name(instruction^.operator)
end;
@@ -1886,21 +1889,21 @@ end;
proc elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral, operand: ^ElnaTacOperand);
begin
operand^.kind := ElnaTacKind.immediate;
operand^.kind := ElnaTacKind.constant;
operand^.value := integer_literal_node^.value;
operand^.length := 0
end;
proc elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral, operand: ^ElnaTacOperand);
begin
operand^.kind := ElnaTacKind.immediate;
operand^.kind := ElnaTacKind.constant;
operand^.value := boolean_literal_node^.value;
operand^.length := 0
end;
proc elna_tac_nil_literal(nil_node: Word, operand: ^ElnaTacOperand);
begin
operand^.kind := ElnaTacKind.immediate;
operand^.kind := ElnaTacKind.constant;
operand^.value := 0;
operand^.length := 0
end;
@@ -1923,7 +1926,7 @@ end;
proc elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLiteral, operand: ^ElnaTacOperand);
begin
operand^.kind := ElnaTacKind.immediate;
operand^.kind := ElnaTacKind.constant;
operand^.value := character_literal_node^.value;
operand^.length := character_literal_node^.length
end;
@@ -1944,22 +1947,11 @@ begin
return result
end;
proc elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression,
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var
lookup_result: ^ElnaSymbolTemporaryInfo;
proc elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression, operand: ^ElnaTacOperand);
begin
lookup_result := elna_symbol_table_lookup(symbol_table, variable_expression^.name, variable_expression^.length);
if lookup_result <> nil then
operand^.kind := ElnaTacKind.pseudo;
operand^.value := variable_expression^.name;
operand^.length := variable_expression^.length
else
operand^.kind := ElnaTacKind.symbol;
operand^.value := variable_expression^.name;
operand^.length := variable_expression^.length
end
operand^.kind := ElnaTacKind.variable;
operand^.value := variable_expression^.name;
operand^.length := variable_expression^.length
end;
proc elna_parser_string_literal(cursor: ^ElnaLexerCursor);
@@ -1990,14 +1982,14 @@ begin
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.symbol, "strings", 7);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.variable, "strings", 7);
elna_list_append(instructions, instruction);
(* Add offset to the string block pointer. *)
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.immediate, offset, 0);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, offset, 0);
elna_list_append(instructions, instruction)
end;
@@ -2099,7 +2091,7 @@ begin
symbol := elna_symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length);
info_type := symbol^._type;
operand^.kind := ElnaTacKind.immediate;
operand^.kind := ElnaTacKind.constant;
operand^.value := info_type^.size;
operand^.length := 0
end;
@@ -2120,7 +2112,7 @@ begin
elsif parser_node^.kind = ElnaTreeKind.trait_expression then
elna_tac_trait_expression(parser_node, operand)
else
elna_tac_variable_expression(parser_node, symbol_table, operand)
elna_tac_variable_expression(parser_node, operand)
end
end;
@@ -2404,7 +2396,7 @@ begin
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call);
elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.symbol, parsed_expression^.name, parsed_expression^.length);
elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.label, parsed_expression^.name, parsed_expression^.length);
elna_tac_instruction_set_operand(call_instruction, 2, ElnaTacKind.list, arguments_operand, parsed_call^.count);
elna_tac_instruction_set_operand(call_instruction, 3, operand^.kind, operand^.value, operand^.length);
@@ -2451,7 +2443,7 @@ begin
memcpy(label_with_dot + 1, parser_node^.label, parser_node^.length);
instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.symbol, label_with_dot, label_length);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.label, label_with_dot, label_length);
elna_list_append(instructions, instruction)
end;
@@ -2512,7 +2504,7 @@ begin
goto elna_tac_enumeration_value_members
end;
(* Found. *)
operand^.kind := ElnaTacKind.immediate;
operand^.kind := ElnaTacKind.constant;
operand^.value := counter;
operand^.length := 0
end
@@ -2640,7 +2632,7 @@ begin
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.immediate, field_offset, 0);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.constant, field_offset, 0);
elna_tac_instruction_set_operand(instruction, 3, operand^.kind, operand^.value, operand^.length);
elna_list_append(instructions, instruction)
end;
@@ -2668,13 +2660,13 @@ begin
instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
elna_tac_instruction_set_operand(instruction, 1, index_type, index_value, index_length);
elna_tac_instruction_set_operand(instruction, 2, inter_operand.kind, inter_operand.value, inter_operand.length);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.immediate, 1, 0);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, 1, 0);
elna_list_append(instructions, instruction);
instruction := elna_tac_instruction_create(ElnaTacOperator.multiply);
elna_tac_instruction_set_operand(instruction, 1, index_type, index_value, index_length);
elna_tac_instruction_set_operand(instruction, 2, index_type, index_value, index_length);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.immediate, element_type^.size, 0);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, element_type^.size, 0);
elna_list_append(instructions, instruction);
elna_tac_designator(instructions, array_access_expression^.array, symbol_table, @is_address, @inter_operand);
@@ -2716,13 +2708,16 @@ var
operand_length: Word;
assignment_operand: ElnaTacOperand;
assignee: ElnaTacOperand;
symbol_info: ^ElnaSymbolInfo;
begin
elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @is_address, @assignee);
(* Compile the assignment. *)
instruction := elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand);
symbol_info := elna_symbol_table_lookup(symbol_table, assignee.value, assignee.length);
if assignee.kind = ElnaTacKind.pseudo then
(* Fix me: if local variable generate different instructions. TAC instructions should not be probably different. *)
if symbol_info <> nil then
if is_address then
instruction := elna_tac_instruction_create(ElnaTacOperator.store);
@@ -2837,13 +2832,13 @@ begin
instruction := elna_tac_instruction_create(ElnaTacOperator.jump_if_zero);
elna_tac_instruction_set_operand(instruction, 1, operand.kind, operand.value, operand.length);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.symbol, condition_label, 0);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.label, condition_label, 0);
elna_list_append(instructions, instruction);
elna_tac_statements(instructions, parser_node^.statements, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.symbol, after_end_label, 0);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.label, after_end_label, 0);
elna_list_append(instructions, instruction);
elna_tac_label(instructions, condition_label, 0)
@@ -3602,7 +3597,6 @@ begin
pseudo_type := malloc(#size(ElnaRtlTypeWord));
pseudo_type^.kind := ElnaRtlTypeKind.long_word;
pseudo_type^.size := 4;
operand_value^ := buffer;
operand_length^ := strlen(buffer);
@@ -3640,12 +3634,12 @@ begin
byte_array := malloc(#size(ElnaRtlTypeByteArray));
byte_array^.kind := ElnaRtlTypeKind.byte_array;
byte_array^.size := variable_info^.variable_type^.size;
byte_array^.alignment := variable_info^.variable_type^.alignment;
pseudo_symbol^.rtl_type := byte_array
else
long_word := malloc(#size(ElnaRtlTypeWord));
long_word^.kind := ElnaRtlTypeKind.long_word;
long_word^.size := variable_info^.variable_type^.size;
pseudo_symbol^.rtl_type := long_word
end;
@@ -4912,6 +4906,7 @@ begin
cursor^.position.end_location.column := 1
end;
(* Returns true of false depending whether to strings are equal. *)
proc string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: Word, rhs_length: Word);
var
result: Word;