diff --git a/boot/stage20/cl.elna b/boot/stage20/cl.elna index 08d6b6c..74dee3c 100644 --- a/boot/stage20/cl.elna +++ b/boot/stage20/cl.elna @@ -8,12 +8,17 @@ program; (* Stage 20 compiler. *) type + ElnaListNode = record + next: Word + end; + ElnaList = record + first: ^ElnaListNode; + last: ^ElnaListNode + end; + (** * List of intermediate representation items. *) - ElnaInstructionList = record - next: Word - end; ElnaInstructionModule = record data: Word; code: Word @@ -308,10 +313,6 @@ type symbol_table: ^ElnaSymbolTable end; - ElnaErrorList = record - first: Word; - last: Word - end; ElnaError = record next: Word end; @@ -475,8 +476,7 @@ type ElnaTacOperand = record kind: ElnaTacKind; value: Word; - length: Word; - offset: Word + length: Word end; ElnaTacInstruction = record next: Word; @@ -487,7 +487,7 @@ type next: Word; name: Word; length: Word; - body: Word; + body: ElnaList; parameters: Word; count: Word; symbol_table: ^ElnaSymbolTable @@ -532,8 +532,7 @@ type ElnaRtlOperand = record kind: ElnaRtlKind; value: Word; - length: Word; - offset: Word + length: Word end; ElnaRtlStaticVariable = record next: Word; @@ -758,6 +757,32 @@ proc _is_alnum(character: Word); return _is_alpha(character) or isdigit(character) end; +proc elna_list_initialize(list: ^ElnaList); +begin + list^.first := nil; + list^.last := nil +end; + +proc elna_list_append(list: ^ElnaList, element: ^ElnaListNode); +begin + if element <> nil then + if list^.first = nil then + list^.first := element + else + list^.last^.next := element + end; + (* TODO: This is a temporary solution for the migration from the old lists. *) + .elna_list_append_loop; + if element^.next = nil then + list^.last := element + else + element := element^.next; + goto elna_list_append_loop + end + end; + return element +end; + proc elna_tac_generate_pseudo(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable); var buffer: Word; @@ -776,7 +801,7 @@ begin elna_symbol_table_enter(symbol_table, buffer, operand_length^, temporary_info) end; -proc elna_instruction_list_concatenate(this: ^ElnaInstructionList, value: Word); +proc elna_instruction_list_concatenate(this: ^ElnaListNode, value: Word); var start: Word; begin @@ -812,7 +837,7 @@ begin result := malloc(#size(ElnaTacInstruction)); result^.operator := kind; - elna_instruction_list_concatenate(result, nil); + result^.next := nil; return result end; @@ -1261,15 +1286,13 @@ begin return result end; -proc elna_tac_label(counter: Word, length: Word); +proc elna_tac_label(instructions: ^ElnaList, counter: Word, length: Word); var result: Word; begin result := elna_tac_instruction_create(ElnaTacOperator.label); - elna_tac_instruction_set_operand(result, 1, ElnaTacKind.symbol, counter, length); - - return result + elna_list_append(instructions, result) end; proc elna_riscv_instruction_name(instruction_kind: Word); @@ -1809,27 +1832,21 @@ proc elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral, ope begin operand^.kind := ElnaTacKind.immediate; operand^.value := integer_literal_node^.value; - operand^.length := 0; - - return nil + operand^.length := 0 end; proc elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral, operand: ^ElnaTacOperand); begin operand^.kind := ElnaTacKind.immediate; operand^.value := boolean_literal_node^.value; - operand^.length := 0; - - return nil + operand^.length := 0 end; proc elna_tac_nil_literal(nil_node: Word, operand: ^ElnaTacOperand); begin operand^.kind := ElnaTacKind.immediate; operand^.value := 0; - operand^.length := 0; - - return nil + operand^.length := 0 end; proc elna_parser_character_literal(); @@ -1851,9 +1868,7 @@ proc elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLitera begin operand^.kind := ElnaTacKind.immediate; operand^.value := character_literal_node^.value; - operand^.length := character_literal_node^.length; - - return nil + operand^.length := character_literal_node^.length end; proc elna_parser_variable_expression(); @@ -1887,8 +1902,7 @@ begin operand^.kind := ElnaTacKind.symbol; operand^.value := variable_expression^.name; operand^.length := variable_expression^.length - end; - return nil + end end; proc elna_parser_string_literal(); @@ -1907,28 +1921,27 @@ begin return result end; -proc elna_tac_string_literal(string_literal_node: ^ElnaTreeStringLiteral, +proc elna_tac_string_literal(instructions: ^ElnaList, string_literal_node: ^ElnaTreeStringLiteral, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var offset: Word; - first_instruction: Word; - next_instruction: Word; + instruction: Word; begin offset := _add_string(string_literal_node^.value); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - first_instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); - elna_tac_instruction_set_operand(first_instruction, 1, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(first_instruction, 2, ElnaTacKind.symbol, "strings", 7); + 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_list_append(instructions, instruction); (* Add offset to the string block pointer. *) - next_instruction := elna_tac_instruction_create(ElnaTacOperator.add); - elna_tac_instruction_set_operand(next_instruction, 1, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(next_instruction, 2, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(next_instruction, 3, ElnaTacKind.immediate, offset, 0); - - return elna_instruction_list_concatenate(first_instruction, next_instruction) + 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_list_append(instructions, instruction) end; proc elna_parser_trait_expression(); @@ -2033,31 +2046,27 @@ begin operand^.kind := ElnaTacKind.immediate; operand^.value := info_type^.size; - operand^.length := 0; - - return nil + operand^.length := 0 end; -proc elna_tac_simple_expression(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); -var - instruction: Word; +proc elna_tac_simple_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeNode, + symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); begin if parser_node^.kind = ElnaTreeKind.character_literal then - instruction := elna_tac_character_literal(parser_node, operand) + elna_tac_character_literal(parser_node, operand) elsif parser_node^.kind = ElnaTreeKind.string_literal then - instruction := elna_tac_string_literal(parser_node, symbol_table, operand) + elna_tac_string_literal(instructions, parser_node, symbol_table, operand) elsif parser_node^.kind = ElnaTreeKind.integer_literal then - instruction := elna_tac_integer_literal(parser_node, operand) + elna_tac_integer_literal(parser_node, operand) elsif parser_node^.kind = ElnaTreeKind.boolean_literal then - instruction := elna_tac_boolean_literal(parser_node, operand) + elna_tac_boolean_literal(parser_node, operand) elsif parser_node^.kind = ElnaTreeKind.null then - instruction := elna_tac_nil_literal(parser_node, operand) + elna_tac_nil_literal(parser_node, operand) elsif parser_node^.kind = ElnaTreeKind.trait_expression then - instruction := elna_tac_trait_expression(parser_node, operand) + elna_tac_trait_expression(parser_node, operand) else - instruction := elna_tac_variable_expression(parser_node, symbol_table, operand) - end; - return instruction + elna_tac_variable_expression(parser_node, symbol_table, operand) + end end; proc elna_parser_unary_expression(); @@ -2095,7 +2104,7 @@ begin return result end; -proc elna_tac_copy_address(is_address: Word, from_type: Word, from_value: Word, from_length: Word, to_type: Word, to_value: Word, to_length: Word); +proc elna_tac_copy_address(instructions: ^ElnaList, is_address: Word, from: ^ElnaTacOperand, to: ^ElnaTacOperand); var instruction: Word; begin @@ -2104,23 +2113,21 @@ begin else instruction := elna_tac_instruction_create(ElnaTacOperator.get_address) end; - elna_tac_instruction_set_operand(instruction, 1, to_type, to_value, to_length); - elna_tac_instruction_set_operand(instruction, 2, from_type, from_value, from_length); + elna_tac_instruction_set_operand(instruction, 1, to^.kind, to^.value, to^.length); + elna_tac_instruction_set_operand(instruction, 2, from^.kind, from^.value, from^.length); - return instruction + elna_list_append(instructions, instruction) end; -proc elna_tac_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); +proc elna_tac_unary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var token_kind: Word; operator: Word; unary_operand: ^ElnaTreeExpression; is_address: Word; - first_instruction: Word; instruction: Word; base: ElnaTacOperand; begin - instruction := nil; if parser_node^.kind = ElnaTreeKind.unary_expression then operator := parser_node^.operator; unary_operand := parser_node^.operand @@ -2128,31 +2135,33 @@ begin operator := 0; unary_operand := parser_node end; - first_instruction := elna_tac_designator(unary_operand, symbol_table, @is_address, @base); + elna_tac_designator(instructions, unary_operand, symbol_table, @is_address, @base); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); if operator = '@' then - instruction := elna_tac_copy_address(is_address, base.kind, base.value, base.length, - operand^.kind, operand^.value, operand^.length) + elna_tac_copy_address(instructions, is_address, @base, operand) elsif operator = '-' then 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_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); + elna_list_append(instructions, instruction) elsif operator = '~' then 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_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); + elna_list_append(instructions, instruction) elsif is_address then 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_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); + elna_list_append(instructions, instruction) else instruction := elna_tac_instruction_create(ElnaTacOperator.copy); 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) - end; - return elna_instruction_list_concatenate(first_instruction, instruction) + elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length); + elna_list_append(instructions, instruction) + end end; proc elna_parser_binary_expression(); @@ -2223,7 +2232,7 @@ begin return result end; -proc elna_tac_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); +proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var first_instruction: Word; instruction: Word; @@ -2231,11 +2240,10 @@ var rhs: ElnaTacOperand; begin if parser_node^.kind <> ElnaTreeKind.binary_expression then - first_instruction := elna_tac_unary_expression(parser_node, symbol_table, operand) + elna_tac_unary_expression(instructions, parser_node, symbol_table, operand) else - first_instruction := elna_tac_unary_expression(parser_node^.lhs, symbol_table, @lhs); - instruction := elna_tac_unary_expression(parser_node^.rhs, symbol_table, @rhs); - first_instruction := elna_instruction_list_concatenate(first_instruction, instruction); + elna_tac_unary_expression(instructions, parser_node^.lhs, symbol_table, @lhs); + 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) @@ -2272,9 +2280,9 @@ begin 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); - first_instruction := elna_instruction_list_concatenate(first_instruction, instruction) + elna_list_append(instructions, instruction) end; - return first_instruction + return instructions^.first end; proc elna_parser_call(callee: Word); @@ -2327,18 +2335,14 @@ begin return result end; -proc elna_tac_call(parsed_call: ^ElnaTreeCall, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); +proc elna_tac_call(instructions: ^ElnaList, parsed_call: ^ElnaTreeCall, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var parsed_expression: ^ElnaTreeVariableExpression; - instruction: Word; - first_instruction: Word; - current_instruction: Word; arguments_operand: ^ElnaTacOperand; call_instruction: Word; argument_entry: ^ElnaTreeExpressionList; begin parsed_expression := parsed_call^.callee; - first_instruction := nil; arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand)); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); @@ -2352,26 +2356,13 @@ begin .elna_tac_call_loop; if argument_entry <> nil then - instruction := elna_tac_binary_expression(argument_entry^.expression, symbol_table, arguments_operand); - if first_instruction = nil then - first_instruction := instruction - else - elna_instruction_list_concatenate(current_instruction, instruction) - end; - if instruction <> nil then - current_instruction := instruction - end; + elna_tac_binary_expression(instructions, argument_entry^.expression, symbol_table, arguments_operand); arguments_operand := arguments_operand + #size(ElnaTacOperand); argument_entry := argument_entry^.next; goto elna_tac_call_loop end; - if first_instruction = nil then - first_instruction := call_instruction - else - elna_instruction_list_concatenate(current_instruction, call_instruction) - end; - return first_instruction + elna_list_append(instructions, call_instruction) end; proc elna_parser_goto_statement(); @@ -2393,21 +2384,21 @@ begin return result end; -proc elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement); +proc elna_tac_goto_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeGotoStatement); var - label_length1: Word; - label_with_dot1: Word; - instruction1: Word; + label_length: Word; + label_with_dot: Word; + instruction: Word; begin - label_length1 := parser_node^.length + 1; - label_with_dot1 := malloc(label_length1); + label_length := parser_node^.length + 1; + label_with_dot := malloc(label_length); - _store_byte('.', label_with_dot1); - memcpy(label_with_dot1 + 1, parser_node^.label, parser_node^.length); + _store_byte('.', label_with_dot); + memcpy(label_with_dot + 1, parser_node^.label, parser_node^.length); - instruction1 := elna_tac_instruction_create(ElnaTacOperator.jump); - elna_tac_instruction_set_operand(instruction1, 1, ElnaTacKind.symbol, label_with_dot1, label_length1); - return instruction1 + instruction := elna_tac_instruction_create(ElnaTacOperator.jump); + elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.symbol, label_with_dot, label_length); + elna_list_append(instructions, instruction) end; proc elna_parser_label_declaration(); @@ -2430,8 +2421,9 @@ begin return result end; -proc elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration); - return elna_tac_label(parser_node^.label, parser_node^.length) +proc elna_tac_label_declaration(instructions: ^ElnaList, parser_node: ^ElnaTreeLabelDeclaration); +begin + elna_tac_label(instructions, parser_node^.label, parser_node^.length) end; proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression, operand: ^ElnaTacOperand); @@ -2473,8 +2465,7 @@ begin operand^.kind := ElnaTacKind.immediate; operand^.value := counter; operand^.length := 0 - end; - return nil + end end; proc elna_parser_field_access_expression(aggregate: Word); @@ -2519,64 +2510,59 @@ begin return result end; -proc elna_tac_dereference_expression(dereference_expression: ^ElnaTreeDereferenceExpression, +proc elna_tac_dereference_expression(instructions: ^ElnaList, dereference_expression: ^ElnaTreeDereferenceExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var - result_instructions: Word; load_instruction: Word; is_address: Word; begin - result_instructions := elna_tac_designator(dereference_expression^.pointer, symbol_table, @is_address, operand); + elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @is_address, operand); if is_address = true then load_instruction := elna_tac_instruction_create(ElnaTacOperator.load); 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); - result_instructions := elna_instruction_list_concatenate(result_instructions, load_instruction) - end; - return result_instructions + elna_list_append(instructions, load_instruction) + end end; -proc elna_tac_designator(parser_node: ^ElnaTreeExpression, symbol_table: ElnaSymbolTable, is_address: Word, operand: ^ElnaTacOperand); +proc elna_tac_designator(instructions: ^ElnaList, parser_node: ^ElnaTreeExpression, symbol_table: ElnaSymbolTable, is_address: Word, operand: ^ElnaTacOperand); var field_access_expression: ^ElnaTreeFieldAccessExpression; - result_instructions: Word; designator_base: ^ElnaTreeExpression; begin if parser_node^.kind = ElnaTreeKind.dereference_expression then - result_instructions := elna_tac_dereference_expression(parser_node, symbol_table, operand); + elna_tac_dereference_expression(instructions, parser_node, symbol_table, operand); is_address^ := true elsif parser_node^.kind = ElnaTreeKind.field_access_expression then field_access_expression := parser_node; designator_base := field_access_expression^.aggregate; if designator_base^.type_decoration = nil then - result_instructions := elna_tac_enumeration_value(field_access_expression, operand); + elna_tac_enumeration_value(field_access_expression, operand); is_address^ := false else - result_instructions := elna_tac_field_access_expression(field_access_expression, symbol_table, operand); + elna_tac_field_access_expression(instructions, field_access_expression, symbol_table, operand); is_address^ := true - end; + end elsif parser_node^.kind = ElnaTreeKind.array_access_expression then - result_instructions := elna_tac_array_access_expression(parser_node, symbol_table, operand); + elna_tac_array_access_expression(instructions, parser_node, symbol_table, operand); is_address^ := true elsif parser_node^.kind = ElnaTreeKind.call then - result_instructions := elna_tac_call(parser_node, symbol_table, operand); + elna_tac_call(instructions, parser_node, symbol_table, operand); is_address^ := false else - result_instructions := elna_tac_simple_expression(parser_node, symbol_table, operand); + elna_tac_simple_expression(instructions, parser_node, symbol_table, operand); is_address^ := false - end; - return result_instructions + end end; -proc elna_tac_field_access_expression(field_access_expression: ^ElnaTreeFieldAccessExpression, +proc elna_tac_field_access_expression(instructions: ^ElnaList, field_access_expression: ^ElnaTreeFieldAccessExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var field_type: ^ElnaType; - first_instruction: Word; - last_instruction: Word; + instruction: Word; designator_base: ^ElnaTreeExpression; aggregate_type: ^ElnaTypeRecord; field_count: Word; @@ -2588,7 +2574,7 @@ begin designator_base := field_access_expression^.aggregate; aggregate_type := designator_base^.type_decoration; - first_instruction := elna_tac_designator(designator_base, symbol_table, @is_address, @base); + elna_tac_designator(instructions, designator_base, symbol_table, @is_address, @base); field_count := aggregate_type^.length; current_field := aggregate_type^.members; @@ -2604,25 +2590,19 @@ begin 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, is_address, @base, operand); - last_instruction := elna_tac_copy_address(is_address, base.kind, base.value, base.length, operand^.kind, operand^.value, operand^.length); - first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction); - - last_instruction := elna_tac_instruction_create(ElnaTacOperator.add); - elna_tac_instruction_set_operand(last_instruction, 1, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacKind.immediate, field_offset, 0); - elna_tac_instruction_set_operand(last_instruction, 3, operand^.kind, operand^.value, operand^.length); - - return elna_instruction_list_concatenate(first_instruction, last_instruction) + 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, 3, operand^.kind, operand^.value, operand^.length); + elna_list_append(instructions, instruction) end; -proc elna_tac_array_access_expression(array_access_expression: ^ElnaTreeArrayAccessExpression, +proc elna_tac_array_access_expression(instructions: ^ElnaList, array_access_expression: ^ElnaTreeArrayAccessExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); var - array_instructions: Word; - index_instructions: Word; - offset_instruction: Word; - add_instruction: Word; + instruction: Word; is_address: Word; inter_operand: ElnaTacOperand; index_type: Word; @@ -2636,36 +2616,32 @@ begin aggregate_type := designator_base^.type_decoration; element_type := aggregate_type^.base; - index_instructions := elna_tac_binary_expression(array_access_expression^.index, symbol_table, @inter_operand); + 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); - add_instruction := elna_tac_instruction_create(ElnaTacOperator.subtract); - elna_tac_instruction_set_operand(add_instruction, 1, index_type, index_value, index_length); - elna_tac_instruction_set_operand(add_instruction, 2, inter_operand.kind, inter_operand.value, inter_operand.length); - elna_tac_instruction_set_operand(add_instruction, 3, ElnaTacKind.immediate, 1, 0); + 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_list_append(instructions, instruction); - offset_instruction := elna_tac_instruction_create(ElnaTacOperator.multiply); - elna_tac_instruction_set_operand(offset_instruction, 1, index_type, index_value, index_length); - elna_tac_instruction_set_operand(offset_instruction, 2, index_type, index_value, index_length); - elna_tac_instruction_set_operand(offset_instruction, 3, ElnaTacKind.immediate, element_type^.size, 0); + 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_list_append(instructions, instruction); - elna_instruction_list_concatenate(add_instruction, offset_instruction); - index_instructions := elna_instruction_list_concatenate(index_instructions, add_instruction); - - array_instructions := elna_tac_designator(array_access_expression^.array, symbol_table, @is_address, @inter_operand); + elna_tac_designator(instructions, array_access_expression^.array, symbol_table, @is_address, @inter_operand); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); - elna_instruction_list_concatenate(offset_instruction, array_instructions); - array_instructions := elna_tac_copy_address(is_address, inter_operand.kind, inter_operand.value, inter_operand.length, - operand^.kind, operand^.value, operand^.length); - elna_instruction_list_concatenate(offset_instruction, array_instructions); + elna_tac_copy_address(instructions, is_address, @inter_operand, operand); - add_instruction := elna_tac_instruction_create(ElnaTacOperator.add); - elna_tac_instruction_set_operand(add_instruction, 1, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(add_instruction, 2, operand^.kind, operand^.value, operand^.length); - elna_tac_instruction_set_operand(add_instruction, 3, index_type, index_value, index_length); + 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, index_type, index_value, index_length); - return elna_instruction_list_concatenate(index_instructions, add_instruction) + elna_list_append(instructions, instruction) end; proc elna_parser_assign_statement(assignee: Word); @@ -2688,70 +2664,60 @@ begin return result end; -proc elna_tac_assign_statement(parser_tree: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable); +proc elna_tac_assign_statement(instructions: ^ElnaList, parser_tree: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable); var is_address: Word; - first_instruction: Word; instruction: Word; - current_instruction: Word; operand_type: Word; operand_value: Word; operand_length: Word; assignment_operand: ElnaTacOperand; assignee: ElnaTacOperand; begin - first_instruction := elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @assignee); + elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @is_address, @assignee); + (* Compile the assignment. *) - instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @assignment_operand); + instruction := elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand); if assignee.kind = ElnaTacKind.pseudo then - current_instruction := elna_tac_instruction_create(ElnaTacOperator.copy); + instruction := elna_tac_instruction_create(ElnaTacOperator.copy); if is_address then elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table); (* Save the assignee address on the stack. *) - elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); - elna_tac_instruction_set_operand(current_instruction, 2, assignee.kind, assignee.value, assignee.length); - first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction); + elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); + elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length); - if instruction <> nil then - elna_instruction_list_concatenate(current_instruction, instruction); - current_instruction := instruction - end; + elna_list_append(instructions, instruction); instruction := elna_tac_instruction_create(ElnaTacOperator.store); elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, assignment_operand.value, assignment_operand.length); elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length); - elna_instruction_list_concatenate(current_instruction, instruction) + elna_list_append(instructions, instruction) else - elna_tac_instruction_set_operand(current_instruction, 1, assignee.kind, assignee.value, assignee.length); - elna_tac_instruction_set_operand(current_instruction, 2, assignment_operand.kind, assignment_operand.value, assignment_operand.length); + elna_tac_instruction_set_operand(instruction, 1, assignee.kind, assignee.value, assignee.length); + elna_tac_instruction_set_operand(instruction, 2, assignment_operand.kind, assignment_operand.value, assignment_operand.length); - first_instruction := elna_instruction_list_concatenate(instruction, current_instruction) + elna_list_append(instructions, instruction) end else elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table); (* Save the assignee address on the stack. *) - current_instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); - elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); - elna_tac_instruction_set_operand(current_instruction, 2, assignee.kind, assignee.value, assignee.length); - first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction); + instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); + elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); + elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length); - if instruction <> nil then - elna_instruction_list_concatenate(current_instruction, instruction); - current_instruction := instruction - end; + elna_list_append(instructions, instruction); instruction := elna_tac_instruction_create(ElnaTacOperator.store); elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, assignment_operand.value, assignment_operand.length); elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length); - elna_instruction_list_concatenate(current_instruction, instruction) - end; - return first_instruction + elna_list_append(instructions, instruction) + end end; proc elna_parser_return_statement(); @@ -2775,18 +2741,16 @@ begin return result end; -proc elna_tac_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable); +proc elna_tac_return_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable); var - first_instruction: Word; instruction: Word; operand: ElnaTacOperand; begin - first_instruction := elna_tac_binary_expression(parser_node^.returned, symbol_table, @operand); + instruction := elna_tac_binary_expression(instructions, parser_node^.returned, symbol_table, @operand); instruction := elna_tac_instruction_create(ElnaTacOperator._return); elna_tac_instruction_set_operand(instruction, 1, operand.kind, operand.value, operand.length); - - return elna_instruction_list_concatenate(first_instruction, instruction) + elna_list_append(instructions, instruction) end; (** @@ -2828,41 +2792,32 @@ begin return result end; -proc elna_tac_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, after_end_label: Word, symbol_table: ^ElnaSymbolTable); +proc elna_tac_conditional_statements(instructions: ^ElnaList, parser_node: ^ElnaTreeConditionalStatements, + after_end_label: Word, symbol_table: ^ElnaSymbolTable); var condition_label: Word; instruction: Word; - current_instruction: Word; - first_instruction: Word; operand: ElnaTacOperand; begin (* Compile condition. *) - first_instruction := elna_tac_binary_expression(parser_node^.condition, symbol_table, @operand); + instruction := elna_tac_binary_expression(instructions, parser_node^.condition, symbol_table, @operand); (* condition_label is the label in front of the next elsif condition or end. *) condition_label := label_counter; label_counter := label_counter + 1; - current_instruction := elna_tac_instruction_create(ElnaTacOperator.jump_if_zero); - elna_tac_instruction_set_operand(current_instruction, 1, operand.kind, operand.value, operand.length); - elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacKind.symbol, condition_label, 0); + 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); - first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction); - - instruction := elna_tac_statements(parser_node^.statements, symbol_table); - if instruction <> nil then - elna_instruction_list_concatenate(current_instruction, instruction); - current_instruction := instruction - end; + 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_instruction_list_concatenate(current_instruction, instruction); + elna_list_append(instructions, instruction); - current_instruction := elna_tac_label(condition_label, 0); - elna_instruction_list_concatenate(instruction, current_instruction); - - return first_instruction + elna_tac_label(instructions, condition_label, 0) end; proc elna_parser_if_statement(); @@ -2961,94 +2916,63 @@ begin return first_statement end; -proc elna_tac_statements(current_statement: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable); -var - instruction: Word; - first_instruction: Word; - current_instruction: Word; +proc elna_tac_statements(instructions: ^ElnaList, current_statement: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable); begin - first_instruction := nil; - .elna_tac_statements_loop; pseudo_counter := 0; if current_statement <> nil then - instruction := elna_tac_statement(current_statement, symbol_table); + elna_tac_statement(instructions, current_statement, symbol_table); current_statement := current_statement^.next; - if instruction = 0 then - goto elna_tac_statements_loop - end; - if first_instruction = nil then - first_instruction := instruction - else - elna_instruction_list_concatenate(current_instruction, instruction) - end; - current_instruction := instruction; + goto elna_tac_statements_loop - end; - return first_instruction + end end; -proc elna_tac_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable); +proc elna_tac_if_statement(instructions: ElnaList, parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable); var current_node: ^ElnaTreeConditionalStatements; after_end_label: Word; condition_label: Word; - first_instruction: Word; - instruction: Word; - current_instruction: Word; begin after_end_label := label_counter; label_counter := label_counter + 1; - current_node := parser_node^.conditionals; - first_instruction := elna_tac_conditional_statements(current_node, after_end_label, symbol_table); - current_instruction := first_instruction; + + elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table); .elna_tac_if_statement_loop; current_node := current_node^.next; if current_node <> nil then - instruction := elna_tac_conditional_statements(current_node, after_end_label, symbol_table); - elna_instruction_list_concatenate(current_instruction, instruction); - current_instruction := instruction; + elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table); + goto elna_tac_if_statement_loop end; current_node := parser_node^._else; if parser_node^._else <> nil then - instruction := elna_tac_statements(parser_node^._else, symbol_table); - if instruction <> 0 then - elna_instruction_list_concatenate(current_instruction, instruction); - current_instruction := instruction - end + elna_tac_statements(instructions, parser_node^._else, symbol_table) end; - instruction := elna_tac_label(after_end_label, 0); - elna_instruction_list_concatenate(current_instruction, instruction); - - return first_instruction + elna_tac_label(instructions, after_end_label, 0) end; -proc elna_tac_statement(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable); +proc elna_tac_statement(instructions: ElnaList, parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable); var - instruction: Word; operand: ElnaTacOperand; begin if parser_node^.kind = ElnaTreeKind.goto_statement then - instruction := elna_tac_goto_statement(parser_node) + elna_tac_goto_statement(instructions, parser_node) elsif parser_node^.kind = ElnaTreeKind.if_statement then - instruction := elna_tac_if_statement(parser_node, symbol_table) + elna_tac_if_statement(instructions, parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.return_statement then - instruction := elna_tac_return_statement(parser_node, symbol_table) + elna_tac_return_statement(instructions, parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.label_declaration then - instruction := elna_tac_label_declaration(parser_node) + elna_tac_label_declaration(instructions, parser_node) elsif parser_node^.kind = ElnaTreeKind.call then - instruction := elna_tac_call(parser_node, symbol_table, @operand) + elna_tac_call(instructions, parser_node, symbol_table, @operand) elsif parser_node^.kind = ElnaTreeKind.assign_statement then - instruction := elna_tac_assign_statement(parser_node, symbol_table) - else - instruction := nil - end; - return instruction + elna_tac_assign_statement(instructions, parser_node, symbol_table) + end end; (** @@ -3738,10 +3662,13 @@ var symbol_info: ^ElnaSymbolProcedureInfo; result: ^ElnaTacProcedure; parameter_count: Word; + body: ElnaList; begin result := malloc(#size(ElnaTacProcedure)); result^.next := nil; + elna_list_initialize(@result^.body); + result^.name := parser_node^.name; result^.length := parser_node^.length; @@ -3751,7 +3678,7 @@ begin result^.parameters := elna_tac_parameters(parser_node^.parameters, @parameter_count); result^.count := parameter_count; - result^.body := elna_tac_statements(parser_node^.body, symbol_info^.symbol_table); + elna_tac_statements(@result^.body, parser_node^.body, symbol_info^.symbol_table); return result end; @@ -4087,7 +4014,7 @@ begin return first_variable end; -proc elna_parser_module_declaration(error_list: ^ElnaErrorList); +proc elna_parser_module_declaration(error_list: ^ElnaList); var parser_node: Word; result: ^ElnaTreeModuleDeclaration; @@ -4480,15 +4407,13 @@ var parser_node: Word; tac: Word; rtl: Word; - error_list: ^ElnaErrorList; + error_list: ElnaList; compiled: Word; begin - error_list := malloc(#size(ElnaErrorList)); - error_list^.first := nil; - error_list^.last := nil; + elna_list_initialize(@error_list); - parser_node := elna_parser_module_declaration(error_list); - compiled := error_list^.first = nil; + parser_node := elna_parser_module_declaration(@error_list); + compiled := error_list.first = nil; if compiled then elna_name_module_declaration(parser_node);