From 8514fb4fa002420a164ced7fffd0df4bb016e5b6 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 3 Apr 2026 18:15:49 +0200 Subject: [PATCH] Implement copy_to_offset and copy_from_offset TAC instructions --- boot/stage19/cl.elna | 8 ++ boot/stage20/cl.elna | 312 +++++++++++++++++++++++++++++-------------- 2 files changed, 218 insertions(+), 102 deletions(-) diff --git a/boot/stage19/cl.elna b/boot/stage19/cl.elna index 5a3916e..8959bfa 100644 --- a/boot/stage19/cl.elna +++ b/boot/stage19/cl.elna @@ -9,6 +9,7 @@ program; (* - Aggregates can be allocated on the stack. *) (* - Procedure return type is parsed. *) +(* - "|" can be used as binary "+" for pointer arithmetic. *) type (** @@ -2167,6 +2168,9 @@ begin elsif token_kind = ElnaLexerKind.minus then _elna_lexer_skip_token(); rhs_node := elna_parser_unary_expression() + elsif token_kind = ElnaLexerKind.pipe then + _elna_lexer_skip_token(); + rhs_node := elna_parser_unary_expression() elsif token_kind = ElnaLexerKind.multiplication then _elna_lexer_skip_token(); rhs_node := elna_parser_unary_expression() @@ -2241,6 +2245,8 @@ begin instruction := elna_tac_instruction_create(ElnaTacOperator.add) elsif parser_node^.operator = ElnaLexerKind.minus then instruction := elna_tac_instruction_create(ElnaTacOperator.subtract) + elsif parser_node^.operator = ElnaLexerKind.pipe then + instruction := elna_tac_instruction_create(ElnaTacOperator.add) elsif parser_node^.operator = ElnaLexerKind.multiplication then instruction := elna_tac_instruction_create(ElnaTacOperator.multiply) elsif parser_node^.operator = ElnaLexerKind.and then @@ -5165,6 +5171,8 @@ begin result := ElnaLexerKind.left_square elsif character = ']' then result := ElnaLexerKind.right_square + elsif character = '|' then + result := ElnaLexerKind.pipe end; return result end; diff --git a/boot/stage20/cl.elna b/boot/stage20/cl.elna index 1ba025b..ee0b555 100644 --- a/boot/stage20/cl.elna +++ b/boot/stage20/cl.elna @@ -503,6 +503,7 @@ type jump_if_not_zero, label, _return, + add_ptr, nop ); ElnaTacKind = (list, label, constant, variable); @@ -841,7 +842,7 @@ begin existing^.next := new end; -proc elna_tac_generate_pseudo(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable); +proc elna_tac_make_variable(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable); var buffer: Word; temporary_info: ^ElnaSymbolTemporaryInfo; @@ -938,9 +939,8 @@ var instruction: ^ElnaRtlInstruction; pseudo_symbol: ^ElnaRtlInfo; begin - rtl_operand^.kind := ElnaRtlKind.pseudo; if tac_operand^.kind = ElnaTacKind.constant then - elna_rtl_generate_pseudo(@rtl_operand^.value, @rtl_operand^.length, variable_map); + elna_rtl_generate_pseudo(rtl_operand, 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, 0); @@ -949,7 +949,7 @@ begin 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); + elna_rtl_generate_pseudo(rtl_operand, 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, 0); @@ -961,6 +961,7 @@ begin elna_rtl_instruction_set_operand(instruction, 2, rtl_operand^.kind, rtl_operand^.value, rtl_operand^.length, 0); elna_list_append(instructions, instruction) else + rtl_operand^.kind := ElnaRtlKind.pseudo; rtl_operand^.value := tac_operand^.value; rtl_operand^.length := tac_operand^.length end @@ -1041,25 +1042,37 @@ begin elna_list_append(instructions, xor_instruction) end; -proc elna_rtl_get_address(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); +proc elna_rtl_operand_address(variable_map: ^ElnaSymbolTable, + addressable: ^ElnaTacOperand, target_operand: ^ElnaRtlOperand) -> ^ElnaRtlInstruction; var pseudo_symbol: ^ElnaRtlInfo; instruction: ^ElnaRtlInstruction; begin - pseudo_symbol := elna_symbol_table_lookup(variable_map, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + pseudo_symbol := elna_symbol_table_lookup(variable_map, addressable^.value, addressable^.length); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); - + elna_rtl_instruction_set_operand(instruction, 1, target_operand^.kind, + target_operand^.value, target_operand^.length, 0); if pseudo_symbol = nil then elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.symbol, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0) + addressable^.value, addressable^.length, 0) else elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, - tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0) + addressable^.value, addressable^.length, 0) end; + return instruction +end; + +proc elna_rtl_get_address(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); +var + instruction: ^ElnaRtlInstruction; + rtl_operand: ElnaRtlOperand; +begin + rtl_operand.kind := ElnaRtlKind.pseudo; + rtl_operand.value := tac_instruction^.operands[2].value; + rtl_operand.length := tac_instruction^.operands[2].length; + + instruction := elna_rtl_operand_address(variable_map, @tac_instruction^.operands[1], @rtl_operand); elna_list_append(instructions, instruction) end; @@ -1142,6 +1155,25 @@ begin elna_list_append(instructions, instruction) end; +proc elna_rtl_copy_to_offset(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); +var + instruction: ^ElnaRtlInstruction; + target_operand: ElnaRtlOperand; + source_operand: ElnaRtlOperand; +begin + elna_rtl_generate_pseudo(@target_operand, variable_map); + instruction := elna_rtl_operand_address(variable_map, @tac_instruction^.operands[2], @target_operand); + elna_list_append(instructions, instruction); + + elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @source_operand); + instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); + + elna_rtl_instruction_set_operand(instruction, 1, source_operand.kind, source_operand.value, source_operand.length, 0); + elna_rtl_instruction_set_operand(instruction, 2, target_operand.kind, target_operand.value, + target_operand.length, tac_instruction^.operands[3].value); + elna_list_append(instructions, instruction) +end; + proc elna_rtl_load(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); var instruction: ^ElnaRtlInstruction; @@ -1150,9 +1182,28 @@ begin elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @rtl_operand); instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); - elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); + elna_rtl_instruction_set_operand(instruction, 2, rtl_operand.kind, rtl_operand.value, rtl_operand.length, 0); + elna_list_append(instructions, instruction) +end; + +proc elna_rtl_copy_from_offset(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); +var + instruction: ^ElnaRtlInstruction; + rtl_operand: ElnaRtlOperand; +begin + rtl_operand.kind := ElnaRtlKind.pseudo; + rtl_operand.value := tac_instruction^.operands[3].value; + rtl_operand.length := tac_instruction^.operands[3].length; + instruction := elna_rtl_operand_address(variable_map, @tac_instruction^.operands[1], @rtl_operand); + elna_list_append(instructions, instruction); + + instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, + tac_instruction^.operands[3].value, tac_instruction^.operands[3].length, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, tac_instruction^.operands[3].value, + tac_instruction^.operands[3].length, tac_instruction^.operands[2].value); elna_list_append(instructions, instruction) end; @@ -1166,11 +1217,10 @@ begin if tac_instruction^.operands[2].kind = ElnaTacKind.variable then elna_rtl_operand_value(instructions, @tac_instruction^.operands[1], variable_map, @source_operand); pseudo_symbol := elna_symbol_table_lookup(variable_map, - tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); if pseudo_symbol = nil then - target_operand.kind := ElnaRtlKind.pseudo; - elna_rtl_generate_pseudo(@target_operand.value, @target_operand.length, variable_map); + elna_rtl_generate_pseudo(@target_operand, variable_map); instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); elna_rtl_instruction_set_operand(instruction, 1, target_operand.kind, target_operand.value, target_operand.length, 0); @@ -1203,8 +1253,12 @@ begin elna_rtl_binary_arithmetic(instructions, tac_instruction, ElnaRtlOperator.add, variable_map) elsif tac_instruction^.operator = ElnaTacOperator.load then elna_rtl_load(instructions, tac_instruction, variable_map) + elsif tac_instruction^.operator = ElnaTacOperator.copy_from_offset then + elna_rtl_copy_from_offset(instructions, tac_instruction, variable_map) elsif tac_instruction^.operator = ElnaTacOperator.store then elna_rtl_store(instructions, tac_instruction, variable_map) + elsif tac_instruction^.operator = ElnaTacOperator.copy_to_offset then + elna_rtl_copy_to_offset(instructions, tac_instruction, variable_map) elsif tac_instruction^.operator = ElnaTacOperator.proc_call then elna_rtl_call(instructions, tac_instruction, variable_map) elsif tac_instruction^.operator = ElnaTacOperator.subtract then @@ -1257,10 +1311,10 @@ begin elna_rtl_copy(instructions, tac_instruction, variable_map) 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_rtl_instruction_set_operand(instruction, 1, tac_instruction^.operands[1].kind, + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); + elna_rtl_instruction_set_operand(instruction, 2, tac_instruction^.operands[2].kind, + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0); elna_list_append(instructions, instruction) end end; @@ -1467,7 +1521,8 @@ begin store_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0, 0); - elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t1, 0, 0); + elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t1, 0, + instruction^.operands[2].offset); pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length, variable_map); @@ -1494,7 +1549,8 @@ begin memcpy(new_instruction, instruction, #size(ElnaRtlInstruction)); new_instruction^.next := nil; - elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t0, 0, 0); + elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.memory, ElnaRtlRegister.t0, 0, + instruction^.operands[2].offset); instruction^.operator := ElnaRtlOperator.lw; @@ -2021,11 +2077,11 @@ proc elna_tac_string_literal(instructions: ^ElnaList, string_literal_node: ^Elna symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var offset: Word; - instruction: Word; + instruction: ^ElnaTacInstruction; begin offset := _add_string(string_literal_node^.value); - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.variable, "strings", 7); @@ -2198,21 +2254,32 @@ begin return result end; -proc elna_tac_copy_address(instructions: ^ElnaList, operand_type: ElnaTacOperandType, from: ^ElnaTacOperand, to: ^ElnaTacOperand); +proc elna_tac_copy_address(instructions: ^ElnaList, operand_result: ^ElnaTacOperandResult, from: ^ElnaTacOperand, to: ^ElnaTacOperand); var - instruction: Word; + instruction: ^ElnaTacInstruction; begin - if operand_type = ElnaTacOperandType.dereferenced_pointer then - instruction := elna_tac_instruction_create(ElnaTacOperator.copy) - elsif operand_type = ElnaTacOperandType.sub_object then - instruction := elna_tac_instruction_create(ElnaTacOperator.copy) - else - instruction := elna_tac_instruction_create(ElnaTacOperator.get_address) - end; - elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length); - elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length); + if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then + instruction := elna_tac_instruction_create(ElnaTacOperator.copy); + elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length); + elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length); + elna_list_append(instructions, instruction) + elsif operand_result^.kind = ElnaTacOperandType.sub_object then + instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); + elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length); + elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length); + elna_list_append(instructions, instruction); - elna_list_append(instructions, instruction) + instruction := elna_tac_instruction_create(ElnaTacOperator.add); + elna_tac_instruction_set_operand(instruction, 1, to^.kind, to^.value, to^.length); + elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.constant, operand_result^.offset, 0); + elna_tac_instruction_set_operand(instruction, 3, to^.kind, to^.value, to^.length); + elna_list_append(instructions, instruction) + else (* ElnaTacOperandType.plain_object *) + instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); + elna_tac_instruction_set_operand(instruction, 1, from^.kind, from^.value, from^.length); + elna_tac_instruction_set_operand(instruction, 2, to^.kind, to^.value, to^.length); + elna_list_append(instructions, instruction) + end end; proc elna_tac_unary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); @@ -2234,35 +2301,36 @@ begin elna_tac_designator(instructions, unary_operand, symbol_table, @operand_result, @base); if operator = '@' then - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - elna_tac_copy_address(instructions, operand_result.kind, @base, operand) + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_copy_address(instructions, @operand_result, @base, operand) elsif operator = '-' then - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); instruction := elna_tac_instruction_create(ElnaTacOperator.negate); elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); elna_list_append(instructions, instruction) elsif operator = '~' then - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); instruction := elna_tac_instruction_create(ElnaTacOperator.complement); elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); elna_list_append(instructions, instruction) elsif operand_result.kind = ElnaTacOperandType.dereferenced_pointer then - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); instruction := elna_tac_instruction_create(ElnaTacOperator.load); elna_tac_instruction_set_operand(instruction, 1, base.kind, base.value, base.length); elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); elna_list_append(instructions, instruction) elsif operand_result.kind = ElnaTacOperandType.sub_object then - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - instruction := elna_tac_instruction_create(ElnaTacOperator.load); + instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset); elna_tac_instruction_set_operand(instruction, 1, base.kind, base.value, base.length); - elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); + elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.constant, operand_result.offset, 0); + elna_tac_instruction_set_operand(instruction, 3, operand^.kind, operand^.value, operand^.length); elna_list_append(instructions, instruction) else operand^.kind := base.kind; @@ -2279,7 +2347,7 @@ var token: ^ElnaLexerToken; begin lhs_node := elna_parser_unary_expression(cursor); - rhs_node := 0; + rhs_node := nil; token := elna_lexer_peek(cursor); if token^.kind = ElnaLexerKind.plus then @@ -2288,6 +2356,9 @@ begin elsif token^.kind = ElnaLexerKind.minus then elna_lexer_read(cursor); rhs_node := elna_parser_unary_expression(cursor) + elsif token^.kind = ElnaLexerKind.pipe then + elna_lexer_read(cursor); + rhs_node := elna_parser_unary_expression(cursor) elsif token^.kind = ElnaLexerKind.multiplication then elna_lexer_read(cursor); rhs_node := elna_parser_unary_expression(cursor) @@ -2339,9 +2410,40 @@ begin return result end; -proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); +proc elna_tac_sum_create(operator: ElnaTacOperator, lhs: ^ElnaTacOperand, rhs: ^ElnaTacOperand, + symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand) -> ^ElnaTacInstruction; var - instruction: Word; + instruction: ^ElnaTacInstruction; +begin + instruction := elna_tac_instruction_create(operator); + + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); + elna_tac_instruction_set_operand(instruction, 2, lhs^.kind, lhs^.value, lhs^.length); + elna_tac_instruction_set_operand(instruction, 3, rhs^.kind, rhs^.value, rhs^.length); + + return instruction +end; + +proc elna_tac_binary_create(operator: ElnaTacOperator, lhs: ^ElnaTacOperand, rhs: ^ElnaTacOperand, + symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand) -> ^ElnaTacInstruction; +var + instruction: ^ElnaTacInstruction; +begin + instruction := elna_tac_instruction_create(operator); + + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); + elna_tac_instruction_set_operand(instruction, 2, lhs^.kind, lhs^.value, lhs^.length); + elna_tac_instruction_set_operand(instruction, 3, rhs^.kind, rhs^.value, rhs^.length); + + return instruction +end; + +proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, + symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); +var + instruction: ^ElnaTacInstruction; lhs: ElnaTacOperand; rhs: ElnaTacOperand; begin @@ -2352,40 +2454,36 @@ begin elna_tac_unary_expression(instructions, parser_node^.rhs, symbol_table, @rhs); if parser_node^.operator = ElnaLexerKind.plus then - instruction := elna_tac_instruction_create(ElnaTacOperator.add) + instruction := elna_tac_binary_create(ElnaTacOperator.add, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.minus then - instruction := elna_tac_instruction_create(ElnaTacOperator.subtract) + instruction := elna_tac_binary_create(ElnaTacOperator.subtract, @lhs, @rhs, symbol_table, operand) + elsif parser_node^.operator = ElnaLexerKind.pipe then + instruction := elna_tac_sum_create(ElnaTacOperator.add, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.multiplication then - instruction := elna_tac_instruction_create(ElnaTacOperator.multiply) + instruction := elna_tac_binary_create(ElnaTacOperator.multiply, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.and then - instruction := elna_tac_instruction_create(ElnaTacOperator.and) + instruction := elna_tac_binary_create(ElnaTacOperator.and, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind._or then - instruction := elna_tac_instruction_create(ElnaTacOperator._or) + instruction := elna_tac_binary_create(ElnaTacOperator._or, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind._xor then - instruction := elna_tac_instruction_create(ElnaTacOperator._xor) + instruction := elna_tac_binary_create(ElnaTacOperator._xor, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.equals then - instruction := elna_tac_instruction_create(ElnaTacOperator.equal) + instruction := elna_tac_binary_create(ElnaTacOperator.equal, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.remainder then - instruction := elna_tac_instruction_create(ElnaTacOperator.remainder) + instruction := elna_tac_binary_create(ElnaTacOperator.remainder, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.division then - instruction := elna_tac_instruction_create(ElnaTacOperator.divide) + instruction := elna_tac_binary_create(ElnaTacOperator.divide, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.less_than then - instruction := elna_tac_instruction_create(ElnaTacOperator.less_than) + instruction := elna_tac_binary_create(ElnaTacOperator.less_than, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.greater_than then - instruction := elna_tac_instruction_create(ElnaTacOperator.greater_than) + instruction := elna_tac_binary_create(ElnaTacOperator.greater_than, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.less_equal then - instruction := elna_tac_instruction_create(ElnaTacOperator.less_or_equal) + instruction := elna_tac_binary_create(ElnaTacOperator.less_or_equal, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.greater_equal then - instruction := elna_tac_instruction_create(ElnaTacOperator.greater_or_equal) + instruction := elna_tac_binary_create(ElnaTacOperator.greater_or_equal, @lhs, @rhs, symbol_table, operand) elsif parser_node^.operator = ElnaLexerKind.not_equal then - instruction := elna_tac_instruction_create(ElnaTacOperator.not_equal) + instruction := elna_tac_binary_create(ElnaTacOperator.not_equal, @lhs, @rhs, symbol_table, operand) end; - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - - elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(instruction, 2, lhs.kind, lhs.value, lhs.length); - elna_tac_instruction_set_operand(instruction, 3, rhs.kind, rhs.value, rhs.length); - elna_list_append(instructions, instruction) end end; @@ -2442,13 +2540,13 @@ proc elna_tac_call(instructions: ^ElnaList, parsed_call: ^ElnaTreeCall, symbol_t var parsed_expression: ^ElnaTreeVariableExpression; arguments_operand: ^ElnaTacOperand; - call_instruction: Word; + call_instruction: ^ElnaTacInstruction; argument_entry: ^ElnaTreeExpressionList; begin parsed_expression := parsed_call^.callee; arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand)); - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_make_variable(@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.label, parsed_expression^.name, parsed_expression^.length); @@ -2489,7 +2587,7 @@ proc elna_tac_goto_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeGoto var label_length: Word; label_with_dot: Word; - instruction: Word; + instruction: ^ElnaTacInstruction; begin label_length := parser_node^.length + 1; label_with_dot := malloc(label_length); @@ -2606,7 +2704,7 @@ end; proc elna_tac_dereference_expression(instructions: ^ElnaList, dereference_expression: ^ElnaTreeDereferenceExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var - load_instruction: Word; + load_instruction: ^ElnaTacInstruction; operand_result: ElnaTacOperandResult; begin elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @operand_result, operand); @@ -2618,10 +2716,10 @@ begin elna_list_append(instructions, load_instruction) elsif operand_result.kind = ElnaTacOperandType.sub_object then - load_instruction := elna_tac_instruction_create(ElnaTacOperator.load); + load_instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset); elna_tac_instruction_set_operand(load_instruction, 1, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(load_instruction, 2, operand^.kind, operand^.value, operand^.length); - + elna_tac_instruction_set_operand(load_instruction, 2, ElnaTacKind.constant, operand_result.offset, 0); + elna_tac_instruction_set_operand(load_instruction, 3, operand^.kind, operand^.value, operand^.length); elna_list_append(instructions, load_instruction) end end; @@ -2645,9 +2743,8 @@ begin if designator_base^.type_decoration = nil then elna_tac_enumeration_value(field_access_expression, operand) else - operand_result^.offset := elna_tac_field_access_expression(instructions, - field_access_expression, symbol_table, operand); - operand_result^.kind := ElnaTacOperandType.sub_object + elna_tac_field_access_expression(instructions, + field_access_expression, symbol_table, operand_result, operand) end elsif parser_node^.kind = ElnaTreeKind.array_access_expression then elna_tac_array_access_expression(instructions, parser_node, symbol_table, operand); @@ -2660,22 +2757,21 @@ begin end; proc elna_tac_field_access_expression(instructions: ^ElnaList, field_access_expression: ^ElnaTreeFieldAccessExpression, - symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand) -> Word; + symbol_table: ^ElnaSymbolTable, operand_result: ^ElnaTacOperandResult, operand: ^ElnaTacOperand); var field_type: ^ElnaType; - instruction: Word; + instruction: ^ElnaTacInstruction; designator_base: ^ElnaTreeExpression; aggregate_type: ^ElnaTypeRecord; field_count: Word; current_field: ^ElnaTypeField; field_offset: Word; - operand_result: ElnaTacOperandResult; base: ElnaTacOperand; begin designator_base := field_access_expression^.aggregate; aggregate_type := designator_base^.type_decoration; - elna_tac_designator(instructions, designator_base, symbol_table, @operand_result, @base); + elna_tac_designator(instructions, designator_base, symbol_table, operand_result, @base); field_count := aggregate_type^.length; current_field := aggregate_type^.members; @@ -2690,22 +2786,29 @@ begin field_offset := field_offset + field_type^.size; goto elna_tac_field_access_expression_field end; - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - elna_tac_copy_address(instructions, operand_result.kind, @base, operand); - 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.constant, field_offset, 0); - elna_tac_instruction_set_operand(instruction, 3, operand^.kind, operand^.value, operand^.length); - elna_list_append(instructions, instruction); + if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - return field_offset + 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, base.kind, base.value, base.length); + elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, field_offset, 0); + elna_list_append(instructions, instruction) + elsif operand_result^.kind = ElnaTacOperandType.sub_object then + memcpy(operand, @base, #size(ElnaTacOperand)); + operand_result^.offset := operand_result^.offset + field_offset + else (* ElnaTacOperandType.plain_object *) + memcpy(operand, @base, #size(ElnaTacOperand)); + operand_result^.kind := ElnaTacOperandType.sub_object; + operand_result^.offset := field_offset + end end; proc elna_tac_array_access_expression(instructions: ^ElnaList, array_access_expression: ^ElnaTreeArrayAccessExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var - instruction: Word; + instruction: ^ElnaTacInstruction; operand_result: ElnaTacOperandResult; inter_operand: ElnaTacOperand; index_type: Word; @@ -2720,7 +2823,7 @@ begin element_type := aggregate_type^.base; elna_tac_binary_expression(instructions, array_access_expression^.index, symbol_table, @inter_operand); - elna_tac_generate_pseudo(@index_type, @index_value, @index_length, symbol_table); + elna_tac_make_variable(@index_type, @index_value, @index_length, symbol_table); instruction := elna_tac_instruction_create(ElnaTacOperator.subtract); elna_tac_instruction_set_operand(instruction, 1, index_type, index_value, index_length); @@ -2736,9 +2839,9 @@ begin elna_tac_designator(instructions, array_access_expression^.array, symbol_table, @operand_result, @inter_operand); - elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); + elna_tac_make_variable(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - elna_tac_copy_address(instructions, operand_result.kind, @inter_operand, operand); + elna_tac_copy_address(instructions, @operand_result, @inter_operand, operand); instruction := elna_tac_instruction_create(ElnaTacOperator.add); elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); @@ -2768,7 +2871,7 @@ end; proc elna_tac_assign_statement(instructions: ^ElnaList, parser_tree: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable); var operand_result: ElnaTacOperandResult; - instruction: Word; + instruction: ^ElnaTacInstruction; assignment_operand: ElnaTacOperand; assignee: ElnaTacOperand; symbol_info: ^ElnaSymbolInfo; @@ -2784,10 +2887,12 @@ begin assignment_operand.value, assignment_operand.length); elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length) elsif operand_result.kind = ElnaTacOperandType.sub_object then - instruction := elna_tac_instruction_create(ElnaTacOperator.store); + instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset); 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) + elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length); + elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, operand_result.offset, 0); + elna_list_append(instructions, instruction) else instruction := elna_tac_instruction_create(ElnaTacOperator.copy); elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, @@ -2818,7 +2923,7 @@ end; proc elna_tac_return_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable); var - instruction: Word; + instruction: ^ElnaTacInstruction; operand: ElnaTacOperand; begin elna_tac_binary_expression(instructions, parser_node^.returned, symbol_table, @operand); @@ -2869,7 +2974,7 @@ proc elna_tac_conditional_statements(instructions: ^ElnaList, parser_node: ^Elna after_end_label: Word, symbol_table: ^ElnaSymbolTable); var condition_label: Word; - instruction: Word; + instruction: ^ElnaTacInstruction; operand: ElnaTacOperand; begin (* Compile condition. *) @@ -3631,12 +3736,13 @@ begin return lhs or rhs end; -proc elna_rtl_generate_pseudo(operand_value: Word, operand_length: Word, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInfo; +proc elna_rtl_generate_pseudo(operand: ^ElnaRtlOperand, variable_map: ^ElnaSymbolTable) -> ^ElnaRtlInfo; var pseudo_symbol: ^ElnaRtlInfo; pseudo_type: ^ElnaRtlTypeWord; buffer: Word; begin + operand^.kind := ElnaRtlKind.pseudo; pseudo_counter := pseudo_counter + 1; pseudo_symbol := malloc(#size(ElnaRtlInfo)); buffer := malloc(7); @@ -3647,11 +3753,11 @@ begin pseudo_type := malloc(#size(ElnaRtlTypeWord)); pseudo_type^.kind := ElnaRtlTypeKind.long_word; - operand_value^ := buffer; - operand_length^ := strlen(buffer); + operand^.value := buffer; + operand^.length := strlen(buffer); pseudo_symbol^.rtl_type := pseudo_type; - elna_symbol_table_enter(variable_map, buffer, operand_length^, pseudo_symbol); + elna_symbol_table_enter(variable_map, buffer, operand^.length, pseudo_symbol); return pseudo_symbol end; @@ -5180,6 +5286,8 @@ begin result := elna_lexer_token_create(ElnaLexerKind.left_square, position) elsif character = ']' then result := elna_lexer_token_create(ElnaLexerKind.right_square, position) + elsif character = '|' then + result := elna_lexer_token_create(ElnaLexerKind.pipe, position) end; return result end;