Make designator independent of hardware registers

This commit is contained in:
2025-12-29 00:33:32 +01:00
parent b4eabfae4e
commit 3db3a0f20e

View File

@@ -1070,11 +1070,6 @@ begin
if operand_type = ElnaTacOperand.symbol then if operand_type = ElnaTacOperand.symbol then
result := elna_rtl_instruction_create(ElnaRtlOperator.la); result := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_copy_operand(tac_instruction, 2, result)
elsif operand_type = ElnaTacOperand.temporary then
result := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_copy_operand(tac_instruction, 1, result); elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_copy_operand(tac_instruction, 2, result) elna_rtl_copy_operand(tac_instruction, 2, result)
elsif operand_type = ElnaTacOperand.pseudo then elsif operand_type = ElnaTacOperand.pseudo then
@@ -1088,13 +1083,7 @@ begin
elsif instruction_kind = ElnaTacOperator.load then elsif instruction_kind = ElnaTacOperator.load then
operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2); operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2);
if operand_type = ElnaTacOperand.temporary then if operand_type = ElnaTacOperand.pseudo then
result := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_copy_operand(tac_instruction, 1, result);
operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.offset, operand_value, 0)
elsif operand_type = ElnaTacOperand.pseudo then
operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2);
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2); operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2);
@@ -1424,6 +1413,81 @@ begin
end end
end; end;
proc elna_alloc_load_address(instruction: ^ElnaInstructionList);
var
operand_type: Word;
operand_value: Word;
operand_length: Word;
pseudo_symbol: Word;
begin
operand_type := elna_rtl_instruction_get_operand_type(instruction, 2);
operand_value := elna_rtl_instruction_get_operand_value(instruction, 2);
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2);
if operand_type = ElnaRtlOperand.pseudo then
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.addi);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.register, ElnaRtlRegister.sp, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol, 0)
end;
operand_type := elna_rtl_instruction_get_operand_type(instruction, 1);
if operand_type = ElnaRtlOperand.pseudo then
elna_alloc_operation_target(instruction)
end
end;
proc elna_alloc_load_store(instruction: ^ElnaInstructionList);
var
old_instruction: ^ElnaInstructionList;
operand_type: Word;
operand_value: Word;
operand_length: Word;
pseudo_symbol: Word;
begin
operand_type := elna_rtl_instruction_get_operand_type(instruction, 1);
operand_value := elna_rtl_instruction_get_operand_value(instruction, 1);
operand_length := elna_rtl_instruction_get_operand_length(instruction, 1);
if operand_type = ElnaRtlOperand.pseudo then
old_instruction := malloc(elna_rtl_instruction_size());
memcpy(old_instruction, instruction, elna_rtl_instruction_size());
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlOperand.register, ElnaRtlRegister.t1, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol);
instruction^.next := old_instruction;
elna_rtl_instruction_set_operand(old_instruction, 1, ElnaRtlOperand.register, ElnaRtlRegister.t1, 0);
goto elna_alloc_load_store_end
end;
operand_type := elna_rtl_instruction_get_operand_type(instruction, 2);
operand_value := elna_rtl_instruction_get_operand_value(instruction, 2);
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2);
if operand_type = ElnaRtlOperand.pseudo then
old_instruction := malloc(elna_rtl_instruction_size());
memcpy(old_instruction, instruction, elna_rtl_instruction_size());
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlOperand.register, ElnaRtlRegister.t1, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol);
instruction^.next := old_instruction;
elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.t1, 0);
goto elna_alloc_load_store_end
end;
.elna_alloc_load_store_end
end;
proc elna_alloc_instruction(instruction: ^ElnaInstructionList); proc elna_alloc_instruction(instruction: ^ElnaInstructionList);
var var
instruction_kind: Word; instruction_kind: Word;
@@ -1466,41 +1530,11 @@ begin
goto elna_alloc_instruction_end goto elna_alloc_instruction_end
end end
elsif instruction_kind = ElnaRtlOperator.la then elsif instruction_kind = ElnaRtlOperator.la then
operand_type := elna_rtl_instruction_get_operand_type(instruction, 2); elna_alloc_load_address(instruction)
operand_value := elna_rtl_instruction_get_operand_value(instruction, 2); elsif instruction_kind = ElnaRtlOperator.lw then
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2); elna_alloc_load_store(instruction)
if operand_type = ElnaRtlOperand.pseudo then
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.addi);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.register, ElnaRtlRegister.sp, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol, 0);
goto elna_alloc_instruction_end
end;
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.sw then elsif instruction_kind = ElnaRtlOperator.sw then
operand_type := elna_rtl_instruction_get_operand_type(instruction, 2); elna_alloc_load_store(instruction)
operand_value := elna_rtl_instruction_get_operand_value(instruction, 2);
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2);
if operand_type = ElnaRtlOperand.pseudo then
old_instruction := malloc(elna_rtl_instruction_size());
memcpy(old_instruction, instruction, elna_rtl_instruction_size());
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlOperand.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol);
instruction^.next := old_instruction;
elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.t2, 0);
goto elna_alloc_instruction_end
end
elsif instruction_kind = ElnaRtlOperator._or then elsif instruction_kind = ElnaRtlOperator._or then
elna_alloc_operation_target(instruction) elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.and then elsif instruction_kind = ElnaRtlOperator.and then
@@ -1941,18 +1975,18 @@ begin
offset := _add_string(string_literal_node^.value); offset := _add_string(string_literal_node^.value);
first_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address); first_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address);
_elna_tac_instruction_set_operand(first_instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(first_instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(first_instruction, 2, ElnaTacOperand.symbol, "strings", 7); _elna_tac_instruction_set_operand(first_instruction, 2, ElnaTacOperand.symbol, "strings", 7);
(* Add offset to the string block pointer. *) (* Add offset to the string block pointer. *)
next_instruction := _elna_tac_instruction_create(ElnaTacOperator.add); next_instruction := _elna_tac_instruction_create(ElnaTacOperator.add);
_elna_tac_instruction_set_operand(next_instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(next_instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(next_instruction, 2, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(next_instruction, 2, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(next_instruction, 3, ElnaTacOperand.immediate, offset, 0); _elna_tac_instruction_set_operand(next_instruction, 3, ElnaTacOperand.immediate, offset, 0);
operand_type^ := ElnaTacOperand.temporary; operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := 6; operand_value^ := "$unary";
operand_length^ := 0; operand_length^ := 6;
return elna_instruction_list_concatenate(first_instruction, next_instruction) return elna_instruction_list_concatenate(first_instruction, next_instruction)
end; end;
@@ -2076,76 +2110,75 @@ end;
proc elna_tac_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word); proc elna_tac_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
var var
current_character: Word;
token_kind: Word; token_kind: Word;
operator: Word; operator: Word;
operand: Word; operand: Word;
is_address: Word; is_address: Word;
first_instruction: Word; first_instruction: Word;
instruction: Word; instruction: Word;
temp: Word;
begin begin
operator := 0; instruction := nil;
operand := 0;
if parser_node^.kind = ElnaTreeKind.unary_expression then if parser_node^.kind = ElnaTreeKind.unary_expression then
operator := parser_node^.operator; operator := parser_node^.operator;
operand := parser_node^.operand operand := parser_node^.operand
else else
operator := 0;
operand := parser_node operand := parser_node
end; end;
first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length);
if operator = '@' then if operator = '@' then
first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length);
instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address); instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^);
operand_type^ := ElnaTacOperand.temporary; operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := 6; operand_value^ := "$unary";
operand_length^ := 0; operand_length^ := 6
elsif operator = '-' then
instruction := _elna_tac_instruction_create(ElnaTacOperator.negate);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^);
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction) operand_type^ := ElnaTacOperand.pseudo;
else operand_value^ := "$unary";
current_character := operand_type^; operand_length^ := 6
first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length); elsif operator = '~' then
operand := operand_type^; instruction := _elna_tac_instruction_create(ElnaTacOperator.complement);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^);
if is_address then operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := "$unary";
operand_length^ := 6
elsif is_address then
if operand_type^ = ElnaTacOperand.pseudo then
instruction := _elna_tac_instruction_create(ElnaTacOperator.load); instruction := _elna_tac_instruction_create(ElnaTacOperator.load);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0);
_elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^);
operand_type^ := ElnaTacOperand.temporary; operand_type^ := ElnaTacOperand.temporary;
operand_value^ := 6; operand_value^ := 6;
operand_length^ := 0; operand_length^ := 0
else
elna_instruction_list_concatenate(first_instruction, instruction) instruction := _elna_tac_instruction_create(ElnaTacOperator.load);
elsif operator = 0 then _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0);
_elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^);
operand_type^ := ElnaTacOperand.temporary; operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := 6; operand_value^ := "$unary";
operand_length^ := 0; operand_length^ := 6
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction)
end end
end; else
if operator = '-' then instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
instruction := _elna_tac_instruction_create(ElnaTacOperator.negate); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0);
_elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^);
elna_instruction_list_concatenate(first_instruction, instruction)
elsif operator = '~' then operand_type^ := ElnaTacOperand.pseudo;
instruction := _elna_tac_instruction_create(ElnaTacOperator.complement); operand_value^ := "$unary";
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); operand_length^ := 6
_elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^);
elna_instruction_list_concatenate(first_instruction, instruction)
end; end;
return first_instruction return elna_instruction_list_concatenate(first_instruction, instruction)
end; end;
proc elna_parser_binary_expression(); proc elna_parser_binary_expression();
@@ -2601,15 +2634,15 @@ begin
first_instruction := elna_tac_designator(dereference_expression^.pointer, symbol_table, is_address, operand_type, operand_value, operand_length); first_instruction := elna_tac_designator(dereference_expression^.pointer, symbol_table, is_address, operand_type, operand_value, operand_length);
last_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); last_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(last_instruction, 2, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(last_instruction, 2, operand_type^, operand_value^, operand_length^);
operand_type^ := ElnaTacOperand.temporary; operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := 6; operand_value^ := "$unary";
operand_length^ := 0; operand_length^ := 6;
is_address^ := 1; is_address^ := 1;
first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction) first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction);
elsif parser_node^.kind = ElnaTreeKind.field_access_expression then elsif parser_node^.kind = ElnaTreeKind.field_access_expression then
field_access_expression := parser_node; field_access_expression := parser_node;
expression_type := field_access_expression^.type_decoration; expression_type := field_access_expression^.type_decoration;
@@ -2635,13 +2668,13 @@ begin
goto elna_tac_designator_field goto elna_tac_designator_field
end; end;
last_instruction := _elna_tac_instruction_create(ElnaTacOperator.add); last_instruction := _elna_tac_instruction_create(ElnaTacOperator.add);
_elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.pseudo, "$unary", 6);
_elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacOperand.immediate, field_offset, 0); _elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacOperand.immediate, field_offset, 0);
_elna_tac_instruction_set_operand(last_instruction, 3, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(last_instruction, 3, operand_type^, operand_value^, operand_length^);
operand_type^ := ElnaTacOperand.temporary; operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := 6; operand_value^ := "$unary";
operand_length^ := 0; operand_length^ := 6;
is_address^ := 1; is_address^ := 1;
first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction) first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction)
@@ -2696,16 +2729,41 @@ begin
first_instruction := elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @operand_type, @operand_value, @operand_length); first_instruction := elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @operand_type, @operand_value, @operand_length);
if operand_type = ElnaTacOperand.pseudo then if operand_type = ElnaTacOperand.pseudo then
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); if is_address then
_elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); (* Save the assignee address on the stack. *)
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.pseudo, "$assign", 7);
_elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
operand_type := 0; (* Compile the assignment. *)
operand_value := 0; operand_type := 0;
operand_length := 0; operand_value := 0;
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length); operand_length := 0;
_elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length); instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
first_instruction := elna_instruction_list_concatenate(instruction, current_instruction) if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end;
instruction := _elna_tac_instruction_create(ElnaTacOperator.store);
_elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$assign", 7);
elna_instruction_list_concatenate(current_instruction, instruction)
else
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length);
operand_type := 0;
operand_value := 0;
operand_length := 0;
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
_elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
first_instruction := elna_instruction_list_concatenate(instruction, current_instruction)
end
else else
(* Save the assignee address on the stack. *) (* Save the assignee address on the stack. *)
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address); current_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address);
@@ -2728,7 +2786,7 @@ begin
_elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); _elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$assign", 7); _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$assign", 7);
elna_instruction_list_concatenate(current_instruction, instruction); elna_instruction_list_concatenate(current_instruction, instruction)
end; end;
return first_instruction return first_instruction
end; end;