From 3db3a0f20e37ba4a9973f9fe9fb9a61df25391f8 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Mon, 29 Dec 2025 00:33:32 +0100 Subject: [PATCH] Make designator independent of hardware registers --- boot/stage17/cl.elna | 276 ++++++++++++++++++++++++++----------------- 1 file changed, 167 insertions(+), 109 deletions(-) diff --git a/boot/stage17/cl.elna b/boot/stage17/cl.elna index c2205a1..ac4ceaa 100644 --- a/boot/stage17/cl.elna +++ b/boot/stage17/cl.elna @@ -1070,11 +1070,6 @@ begin if operand_type = ElnaTacOperand.symbol then 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, 2, result) elsif operand_type = ElnaTacOperand.pseudo then @@ -1088,13 +1083,7 @@ begin elsif instruction_kind = ElnaTacOperator.load then operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2); - if operand_type = ElnaTacOperand.temporary 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 + if operand_type = ElnaTacOperand.pseudo then operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2); @@ -1424,6 +1413,81 @@ begin 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); var instruction_kind: Word; @@ -1466,41 +1530,11 @@ begin goto elna_alloc_instruction_end end elsif instruction_kind = ElnaRtlOperator.la then - 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); - - goto elna_alloc_instruction_end - end; - - elna_alloc_operation_target(instruction) + elna_alloc_load_address(instruction) + elsif instruction_kind = ElnaRtlOperator.lw then + elna_alloc_load_store(instruction) elsif instruction_kind = ElnaRtlOperator.sw then - 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.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 + elna_alloc_load_store(instruction) elsif instruction_kind = ElnaRtlOperator._or then elna_alloc_operation_target(instruction) elsif instruction_kind = ElnaRtlOperator.and then @@ -1941,18 +1975,18 @@ begin offset := _add_string(string_literal_node^.value); 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); (* Add offset to the string block pointer. *) 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, 2, 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.pseudo, "$unary", 6); _elna_tac_instruction_set_operand(next_instruction, 3, ElnaTacOperand.immediate, offset, 0); - operand_type^ := ElnaTacOperand.temporary; - operand_value^ := 6; - operand_length^ := 0; + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + operand_length^ := 6; return elna_instruction_list_concatenate(first_instruction, next_instruction) 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); var - current_character: Word; token_kind: Word; operator: Word; operand: Word; is_address: Word; first_instruction: Word; instruction: Word; - temp: Word; begin - operator := 0; - operand := 0; - + instruction := nil; if parser_node^.kind = ElnaTreeKind.unary_expression then operator := parser_node^.operator; operand := parser_node^.operand else + operator := 0; operand := parser_node end; + first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length); 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); - _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^); - operand_type^ := ElnaTacOperand.temporary; - operand_value^ := 6; - operand_length^ := 0; + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + 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) - else - current_character := operand_type^; - first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length); - operand := operand_type^; + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + operand_length^ := 6 + elsif operator = '~' then + 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); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); operand_type^ := ElnaTacOperand.temporary; operand_value^ := 6; - operand_length^ := 0; - - elna_instruction_list_concatenate(first_instruction, instruction) - elsif operator = 0 then - instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); - _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); + operand_length^ := 0 + else + instruction := _elna_tac_instruction_create(ElnaTacOperator.load); + _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$unary", 6); _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); - operand_type^ := ElnaTacOperand.temporary; - operand_value^ := 6; - operand_length^ := 0; - - first_instruction := elna_instruction_list_concatenate(first_instruction, instruction) + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + operand_length^ := 6 end - end; - if operator = '-' then - instruction := _elna_tac_instruction_create(ElnaTacOperator.negate); - _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); + else + instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); + _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_instruction_list_concatenate(first_instruction, instruction) - elsif operator = '~' then - instruction := _elna_tac_instruction_create(ElnaTacOperator.complement); - _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_instruction_list_concatenate(first_instruction, instruction) + + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + operand_length^ := 6 end; - return first_instruction + return elna_instruction_list_concatenate(first_instruction, instruction) end; 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); 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^); - operand_type^ := ElnaTacOperand.temporary; - operand_value^ := 6; - operand_length^ := 0; + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + operand_length^ := 6; 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 field_access_expression := parser_node; expression_type := field_access_expression^.type_decoration; @@ -2635,13 +2668,13 @@ begin goto elna_tac_designator_field end; 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, 3, operand_type^, operand_value^, operand_length^); - operand_type^ := ElnaTacOperand.temporary; - operand_value^ := 6; - operand_length^ := 0; + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + operand_length^ := 6; is_address^ := 1; 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); if operand_type = ElnaTacOperand.pseudo then - current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); - _elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); + if is_address then + (* 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; - 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); + (* Compile the assignment. *) + 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); - 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 (* Save the assignee address on the stack. *) 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, 2, ElnaTacOperand.pseudo, "$assign", 7); - elna_instruction_list_concatenate(current_instruction, instruction); + elna_instruction_list_concatenate(current_instruction, instruction) end; return first_instruction end;