diff --git a/boot/stage20/cl.elna b/boot/stage20/cl.elna index 1ba025b..8c97a74 100644 --- a/boot/stage20/cl.elna +++ b/boot/stage20/cl.elna @@ -1142,6 +1142,46 @@ begin elna_list_append(instructions, instruction) end; +proc elna_rtl_copy_to_offset(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); +var + pseudo_symbol: ^ElnaRtlInfo; + instruction: ^ElnaRtlInstruction; + target_operand: ElnaRtlOperand; + source_operand: ElnaRtlOperand; +begin + target_operand.kind := ElnaRtlKind.pseudo; + elna_rtl_generate_pseudo(@target_operand.value, @target_operand.length, variable_map); + + pseudo_symbol := elna_symbol_table_lookup(variable_map, + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length); + instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); + + 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[2].value, tac_instruction^.operands[2].length, 0) + else + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, + tac_instruction^.operands[2].value, tac_instruction^.operands[2].length, 0) + end; + elna_list_append(instructions, instruction); + + instruction := elna_rtl_instruction_create(ElnaRtlOperator.addi); + elna_rtl_instruction_set_operand(instruction, 1, target_operand.kind, target_operand.value, target_operand.length, 0); + elna_rtl_instruction_set_operand(instruction, 2, target_operand.kind, target_operand.value, target_operand.length, 0); + elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, tac_instruction^.operands[3].value, 0, 0); + 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, 0); + elna_list_append(instructions, instruction) +end; + proc elna_rtl_load(instructions: ^ElnaList, tac_instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable); var instruction: ^ElnaRtlInstruction; @@ -1150,9 +1190,44 @@ 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; + pseudo_symbol: ^ElnaRtlInfo; +begin + pseudo_symbol := elna_symbol_table_lookup(variable_map, + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length); + instruction := elna_rtl_instruction_create(ElnaRtlOperator.la); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, + tac_instruction^.operands[3].value, tac_instruction^.operands[3].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) + else + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.pseudo, + tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0) + end; + elna_list_append(instructions, instruction); + + instruction := elna_rtl_instruction_create(ElnaRtlOperator.addi); + 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, 0); + elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, tac_instruction^.operands[2].value, 0, 0); + 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, 0); elna_list_append(instructions, instruction) end; @@ -1203,8 +1278,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 +1336,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; @@ -2021,7 +2100,7 @@ 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); @@ -2198,21 +2277,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); @@ -2235,7 +2325,7 @@ begin 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_copy_address(instructions, @operand_result, @base, operand) elsif operator = '-' then elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); @@ -2260,9 +2350,10 @@ begin elsif operand_result.kind = ElnaTacOperandType.sub_object then elna_tac_generate_pseudo(@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; @@ -2341,7 +2432,7 @@ end; proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var - instruction: Word; + instruction: ^ElnaTacInstruction; lhs: ElnaTacOperand; rhs: ElnaTacOperand; begin @@ -2442,7 +2533,7 @@ 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; @@ -2489,7 +2580,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 +2697,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 +2709,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 +2736,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 +2750,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 +2779,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_generate_pseudo(@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; @@ -2738,7 +2834,7 @@ begin symbol_table, @operand_result, @inter_operand); elna_tac_generate_pseudo(@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,9 +2864,10 @@ 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; + operand: ElnaTacOperand; symbol_info: ^ElnaSymbolInfo; begin elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @operand_result, @assignee); @@ -2784,10 +2881,14 @@ 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); + elna_tac_generate_pseudo(@operand.kind, @operand.value, @operand.length, symbol_table); + + 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 +2919,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 +2970,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. *)