From 953447dc238220aa128f14b398e1913ad3f94862 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 14 Mar 2026 21:39:53 +0100 Subject: [PATCH] Handle TAC global and local variables --- boot/stage20/cl.elna | 149 +++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 77 deletions(-) diff --git a/boot/stage20/cl.elna b/boot/stage20/cl.elna index bd05299..64e1fb9 100644 --- a/boot/stage20/cl.elna +++ b/boot/stage20/cl.elna @@ -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;