aboutsummaryrefslogtreecommitdiff
path: root/source/tac.elna
diff options
context:
space:
mode:
Diffstat (limited to 'source/tac.elna')
-rw-r--r--source/tac.elna1074
1 files changed, 0 insertions, 1074 deletions
diff --git a/source/tac.elna b/source/tac.elna
deleted file mode 100644
index 3d65e42..0000000
--- a/source/tac.elna
+++ /dev/null
@@ -1,1074 +0,0 @@
-(* This Source Code Form is subject to the terms of the Mozilla Public License,
- v. 2.0. If a copy of the MPL was not distributed with this file, You can
- obtain one at https://mozilla.org/MPL/2.0/. *)
-module
-import common, sys.posix.cstdlib, sys.posix.cstdio, sys.posix.cstring, lexer, ast, symbol, diagnostic
-
-type
- ElnaTacOperator* = (
- get_address,
- add,
- load,
- store,
- proc_call,
- copy,
- copy_to_offset,
- copy_from_offset,
- subtract,
- divide,
- remainder,
- multiply,
- _xor,
- _or,
- and,
- less_than,
- greater_than,
- less_or_equal,
- greater_or_equal,
- equal,
- not_equal,
- negate,
- complement,
- jump,
- jump_if_zero,
- jump_if_not_zero,
- label,
- _return,
- add_ptr,
- nop
- )
-
- ElnaTacKind* = (list, label, constant, variable, ignore)
-
- ElnaTacOperand* = record
- kind: ElnaTacKind;
- name: []const Word8;
- constant: Word;
- length: Word;
- list_operands: ^ElnaTacOperand
- end
-
- ElnaTacInstruction* = record(ElnaListNode)
- operator: ElnaTacOperator;
- operands: [4]ElnaTacOperand
- end
-
- ElnaTacProcedure* = record
- next: ^ElnaTacProcedure;
- name: []const Word8;
- body: ElnaList;
- parameters: ^[]const Word8;
- count: Word;
- symbol_table: ^ElnaSymbolTable
- end
-
- ElnaTacStaticVariable* = record
- next: ^ElnaTacStaticVariable;
- name: []const Word8;
- size: Word
- end
-
- ElnaTacStringConstant* = record
- next: ^ElnaTacStringConstant;
- name: []const Word8;
- value: []const Word8
- end
-
- ElnaInstructionModule* = record
- strings: ^ElnaTacStringConstant;
- data: ^ElnaTacStaticVariable;
- code: ^ElnaTacProcedure
- end
-
- ElnaTacOperandType = (plain_object, dereferenced_pointer, sub_object)
-
- ElnaTacOperandResult = record
- kind: ElnaTacOperandType;
- offset: Word
- end
-
-var
- pseudo_counter: Word := 0u
- label_counter: Word := 0u
- string_counter: Word := 0u
- module_strings_first: ^ElnaTacStringConstant := nil
- module_strings_last: ^ElnaTacStringConstant := nil
-
-proc elna_tac_instruction_create*(operator: ElnaTacOperator) -> ^ElnaTacInstruction
-var
- result: ^ElnaTacInstruction
-begin
- result := malloc#[ElnaTacInstruction](#size(ElnaTacInstruction));
- result^.next := nil;
- result^.operator := operator;
- result^.operands[1].kind := ElnaTacKind.ignore;
- result^.operands[2].kind := ElnaTacKind.ignore;
- result^.operands[3].kind := ElnaTacKind.ignore;
- result^.operands[4].kind := ElnaTacKind.ignore
-return result
-
-proc elna_tac_instruction_set_operand*(this: ^ElnaTacInstruction; n: Word;
- kind: ElnaTacKind; name: []const Word8; constant: Word; length: Word)
-begin
- this^.operands[n].kind := kind;
- this^.operands[n].name := name;
- this^.operands[n].constant := constant;
- this^.operands[n].length := length;
- this^.operands[n].list_operands := nil
-return
-
-proc elna_tac_instruction_set_op*(this: ^ElnaTacInstruction; n: Word; op: ^ElnaTacOperand)
-begin
- this^.operands[n] := op^
-return
-
-proc elna_tac_instruction_set_const*(this: ^ElnaTacInstruction; n: Word; value: Word; length: Word)
-begin
- this^.operands[n].kind := ElnaTacKind.constant;
- this^.operands[n].name := "";
- this^.operands[n].constant := value;
- this^.operands[n].length := length;
- this^.operands[n].list_operands := nil
-return
-
-proc elna_tac_instruction_set_label*(this: ^ElnaTacInstruction; n: Word; label_name: []const Word8)
-begin
- this^.operands[n].kind := ElnaTacKind.label;
- this^.operands[n].name := label_name;
- this^.operands[n].constant := 0u;
- this^.operands[n].length := label_name.length;
- this^.operands[n].list_operands := nil
-return
-
-proc elna_tac_make_variable*(operand: ^ElnaTacOperand; symbol_table: ^ElnaSymbolTable; variable_type: ^ElnaType)
-var
- buffer: ^Word8
- name_slice: []const Word8
- temporary_info: ^ElnaSymbolTemporaryInfo
- len: Int
-begin
- pseudo_counter := pseudo_counter + 1u;
- buffer := malloc#[Word8](16u);
- len := sprintf(buffer, "t%u\0".ptr, pseudo_counter);
-
- name_slice := buffer[1u to cast(len: Word)];
-
- operand^.kind := ElnaTacKind.variable;
- operand^.name := name_slice;
- operand^.constant := 0u;
- operand^.length := name_slice.length;
- operand^.list_operands := nil;
-
- temporary_info := elna_symbol_temporary_info_create(1u, variable_type);
- elna_symbol_table_enter(symbol_table, name_slice, cast(temporary_info: ^ElnaSymbolInfo))
-return
-
-proc elna_tac_label*() -> []const Word8
-var
- buffer: ^Word8
- result: []const Word8
- len: Int
-begin
- label_counter := label_counter + 1u;
- buffer := malloc#[Word8](16u);
- len := sprintf(buffer, "l%u\0".ptr, label_counter);
- result := buffer[1u to cast(len: Word)]
-return result
-
-proc elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.constant := integer_literal_node^.value;
- operand^.length := word_type^.size;
- operand^.list_operands := nil
-return
-
-proc elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- if boolean_literal_node^.value then
- operand^.constant := 1u
- else
- operand^.constant := 0u
- end;
- operand^.length := bool_type^.size;
- operand^.list_operands := nil
-return
-
-proc elna_tac_nil_literal(operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.constant := 0u;
- operand^.length := 8u;
- operand^.list_operands := nil
-return
-
-proc elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLiteral; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.constant := cast(character_literal_node^.value: Word);
- operand^.length := char_type^.size;
- operand^.list_operands := nil
-return
-
-proc elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.variable;
- operand^.name := variable_expression^.name;
- operand^.constant := 0u;
- operand^.length := variable_expression^.name.length;
- operand^.list_operands := nil
-return
-
-proc elna_tac_trait_expression(trait_node: ^ElnaTreeTraitExpression; operand: ^ElnaTacOperand)
-var
- symbol_info: ^ElnaSymbolInfo
- type_info: ^ElnaSymbolTypeInfo
- parser_node: ^ElnaTreeNamedTypeExpression
-begin
- parser_node := cast(trait_node^.argument: ^ElnaTreeNamedTypeExpression);
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name);
-
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.length := 8u;
- operand^.list_operands := nil;
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.type_info then
- type_info := cast(symbol_info: ^ElnaSymbolTypeInfo);
- operand^.constant := type_info^._type^.size
- else
- operand^.constant := 0u
- end
-return
-
-proc elna_tac_string_literal(instructions: ^ElnaList; string_literal_node: ^ElnaTreeStringLiteral;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- string_entry: ^ElnaTacStringConstant
- label_buf: ^Word8
- label_slice: []const Word8
- label_len: Int
- instruction: ^ElnaTacInstruction
- address: ElnaTacOperand
-begin
- string_counter := string_counter + 1u;
- label_buf := malloc#[Word8](16u);
- label_len := sprintf(label_buf, "str_%u\0".ptr, string_counter);
- label_slice := label_buf[1u to cast(label_len: Word)];
-
- string_entry := malloc#[ElnaTacStringConstant](#size(ElnaTacStringConstant));
- string_entry^.next := nil;
- string_entry^.name := label_slice;
- string_entry^.value := string_literal_node^.value;
-
- if module_strings_first = nil then
- module_strings_first := string_entry
- else
- module_strings_last^.next := string_entry
- end;
- module_strings_last := string_entry;
-
- elna_tac_make_variable(operand, symbol_table, cast(string_type: ^ElnaType));
- elna_tac_make_variable(@address, symbol_table, pointer_type);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
- elna_tac_instruction_set_operand(instruction, 1u, ElnaTacKind.variable, label_slice, 0u, label_slice.length);
- elna_tac_instruction_set_op(instruction, 2u, @address);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
- elna_tac_instruction_set_op(instruction, 1u, @address);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_tac_instruction_set_const(instruction, 3u, 0u, 8u);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
- elna_tac_instruction_set_const(instruction, 1u, string_literal_node^.value.length, 8u);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_tac_instruction_set_const(instruction, 3u, 8u, 8u);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_copy_address(instructions: ^ElnaList; operand_result: ^ElnaTacOperandResult; from, dest: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
-begin
- if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then
- dest^ := from^
- elsif operand_result^.kind = ElnaTacOperandType.sub_object then
- instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
- elna_tac_instruction_set_op(instruction, 1u, from);
- elna_tac_instruction_set_op(instruction, 2u, dest);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.add);
- elna_tac_instruction_set_const(instruction, 1u, operand_result^.offset, 4u);
- elna_tac_instruction_set_op(instruction, 2u, dest);
- elna_tac_instruction_set_op(instruction, 3u, dest);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
- elna_tac_instruction_set_op(instruction, 1u, from);
- elna_tac_instruction_set_op(instruction, 2u, dest);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- end
-return
-
-proc elna_tac_simple_expression(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-begin
- case parser_node^.kind of
- ElnaTreeKind.integer_literal:
- elna_tac_integer_literal(cast(parser_node: ^ElnaTreeIntegerLiteral), operand)
- | ElnaTreeKind.character_literal:
- elna_tac_character_literal(cast(parser_node: ^ElnaTreeCharacterLiteral), operand)
- | ElnaTreeKind.string_literal:
- elna_tac_string_literal(instructions, cast(parser_node: ^ElnaTreeStringLiteral), symbol_table, operand)
- | ElnaTreeKind.boolean_literal:
- elna_tac_boolean_literal(cast(parser_node: ^ElnaTreeBooleanLiteral), operand)
- | ElnaTreeKind.null:
- elna_tac_nil_literal(operand)
- | ElnaTreeKind.variable_expression:
- elna_tac_variable_expression(cast(parser_node: ^ElnaTreeVariableExpression), operand)
- | ElnaTreeKind.trait_expression:
- elna_tac_trait_expression(cast(parser_node: ^ElnaTreeTraitExpression), operand)
- | ElnaTreeKind._cast:
- elna_tac_binary_expression(instructions, (cast(parser_node: ^ElnaTreeCastExpression))^.expression, symbol_table, operand)
- else
- end
-return
-
-proc elna_tac_unary_expression(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- operator: ElnaLexerKind
- unary_operand: ^ElnaTreeExpression
- unary_node: ^ElnaTreeUnaryExpression
- operand_result: ElnaTacOperandResult
- instruction: ^ElnaTacInstruction
- base: ElnaTacOperand
- has_unary: Bool := false
-begin
- if parser_node^.kind = ElnaTreeKind.unary_expression then
- unary_node := cast(parser_node: ^ElnaTreeUnaryExpression);
- operator := unary_node^.operator;
- unary_operand := unary_node^.operand;
- has_unary := true
- else
- unary_operand := parser_node
- end;
- elna_tac_designator(instructions, unary_operand, symbol_table, @operand_result, @base);
-
- if has_unary & operator = ElnaLexerKind.at then
- elna_tac_make_variable(operand, symbol_table, word_type);
- elna_tac_copy_address(instructions, @operand_result, @base, operand)
- elsif has_unary & operator = ElnaLexerKind.minus then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif has_unary & operator = ElnaLexerKind.not then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.complement);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif operand_result.kind = ElnaTacOperandType.dereferenced_pointer then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.load);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif operand_result.kind = ElnaTacOperandType.sub_object then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_const(instruction, 2u, operand_result.offset, 4u);
- elna_tac_instruction_set_op(instruction, 3u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- operand^ := base
- end
-return
-
-proc elna_tac_add_pointer(parser_node: ^ElnaTreeExpression; lhs, rhs: ^ElnaTacOperand;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand) -> ^ElnaTacInstruction
-var
- instruction: ^ElnaTacInstruction
- pointer_type_node: ^ElnaTypePointer
- elem_size: Word := 1u
-begin
- if parser_node^.type_decoration <> nil & parser_node^.type_decoration^.kind = ElnaTypeKind.pointer then
- pointer_type_node := cast(parser_node^.type_decoration: ^ElnaTypePointer);
- if pointer_type_node^.base <> nil then
- elem_size := pointer_type_node^.base^.size
- end
- end;
- instruction := elna_tac_instruction_create(ElnaTacOperator.add_ptr);
- elna_tac_make_variable(operand, symbol_table, word_type);
- elna_tac_instruction_set_op(instruction, 1u, lhs);
- elna_tac_instruction_set_op(instruction, 2u, rhs);
- elna_tac_instruction_set_const(instruction, 3u, elem_size, 4u);
- elna_tac_instruction_set_op(instruction, 4u, operand)
-return instruction
-
-proc elna_tac_binary_create(instructions: ^ElnaList; operator: ElnaTacOperator;
- lhs, rhs: ^ElnaTacOperand; symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
- lhs_symbol: ^ElnaSymbolInfo
- temp_info: ^ElnaSymbolTemporaryInfo
- variable_type: ^ElnaType := word_type
-begin
- if lhs^.kind = ElnaTacKind.variable then
- lhs_symbol := elna_symbol_table_lookup(symbol_table, lhs^.name);
- if lhs_symbol <> nil & lhs_symbol^.kind = ElnaSymbolInfoKind.temporary_info then
- temp_info := cast(lhs_symbol: ^ElnaSymbolTemporaryInfo);
- variable_type := temp_info^.variable_type
- end
- end;
- elna_tac_make_variable(operand, symbol_table, variable_type);
-
- instruction := elna_tac_instruction_create(operator);
- elna_tac_instruction_set_op(instruction, 1u, lhs);
- elna_tac_instruction_set_op(instruction, 2u, rhs);
- elna_tac_instruction_set_op(instruction, 3u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_subtract_create(instructions: ^ElnaList; parser_node: ^ElnaTreeBinaryExpression;
- lhs, rhs: ^ElnaTacOperand; symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
- lhs_is_pointer: Bool := false
- rhs_is_not_pointer: Bool := true
-begin
- if parser_node^.lhs^.type_decoration <> nil & parser_node^.lhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- lhs_is_pointer := true
- end;
- if parser_node^.rhs^.type_decoration <> nil & parser_node^.rhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- rhs_is_not_pointer := false
- end;
-
- if lhs_is_pointer & rhs_is_not_pointer then
- instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
- elna_tac_instruction_set_op(instruction, 1u, rhs);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_add_pointer(parser_node^.lhs, lhs, operand, symbol_table, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- elna_tac_binary_create(instructions, ElnaTacOperator.subtract, lhs, rhs, symbol_table, operand)
- end
-return
-
-proc elna_tac_binary_expression(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- binary_node: ^ElnaTreeBinaryExpression
- instruction: ^ElnaTacInstruction
- lhs: ElnaTacOperand
- rhs: ElnaTacOperand
-begin
- if parser_node^.kind <> ElnaTreeKind.binary_expression then
- elna_tac_unary_expression(instructions, parser_node, symbol_table, operand)
- else
- binary_node := cast(parser_node: ^ElnaTreeBinaryExpression);
- elna_tac_unary_expression(instructions, binary_node^.lhs, symbol_table, @lhs);
- elna_tac_unary_expression(instructions, binary_node^.rhs, symbol_table, @rhs);
-
- case binary_node^.operator of
- ElnaLexerKind.plus:
- if binary_node^.lhs^.type_decoration <> nil & binary_node^.lhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- instruction := elna_tac_add_pointer(binary_node^.lhs, @lhs, @rhs, symbol_table, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif binary_node^.rhs^.type_decoration <> nil & binary_node^.rhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- instruction := elna_tac_add_pointer(binary_node^.rhs, @rhs, @lhs, symbol_table, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- elna_tac_binary_create(instructions, ElnaTacOperator.add, @lhs, @rhs, symbol_table, operand)
- end
- | ElnaLexerKind.minus:
- elna_tac_subtract_create(instructions, binary_node, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.multiplication:
- elna_tac_binary_create(instructions, ElnaTacOperator.multiply, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.division:
- elna_tac_binary_create(instructions, ElnaTacOperator.divide, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.remainder:
- elna_tac_binary_create(instructions, ElnaTacOperator.remainder, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.and:
- elna_tac_binary_create(instructions, ElnaTacOperator.and, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind._or:
- elna_tac_binary_create(instructions, ElnaTacOperator._or, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind._xor:
- elna_tac_binary_create(instructions, ElnaTacOperator._xor, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.equals:
- elna_tac_binary_create(instructions, ElnaTacOperator.equal, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.not_equal:
- elna_tac_binary_create(instructions, ElnaTacOperator.not_equal, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.less_than:
- elna_tac_binary_create(instructions, ElnaTacOperator.less_than, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.greater_than:
- elna_tac_binary_create(instructions, ElnaTacOperator.greater_than, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.less_equal:
- elna_tac_binary_create(instructions, ElnaTacOperator.less_or_equal, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.greater_equal:
- elna_tac_binary_create(instructions, ElnaTacOperator.greater_or_equal, @lhs, @rhs, symbol_table, operand)
- else
- end
- end
-return
-
-proc elna_tac_call(instructions: ^ElnaList; parsed_call: ^ElnaTreeCall; symbol_table: ^ElnaSymbolTable;
- operand: ^ElnaTacOperand)
-var
- parsed_expression: ^ElnaTreeVariableExpression
- arguments_operand: ^ElnaTacOperand
- call_instruction: ^ElnaTacInstruction
- argument_entry: ^ElnaTreeExpressionList
- symbol_info: ^ElnaSymbolInfo
- procedure_info: ^ElnaSymbolProcedureInfo
- i: Word := 0u
-begin
- parsed_expression := parsed_call^.callee;
- arguments_operand := malloc#[ElnaTacOperand](parsed_call^.count * #size(ElnaTacOperand));
- symbol_info := elna_symbol_table_lookup(symbol_table, parsed_expression^.name);
-
- call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call);
- elna_tac_instruction_set_label(call_instruction, 1u, parsed_expression^.name);
-
- call_instruction^.operands[2].kind := ElnaTacKind.list;
- call_instruction^.operands[2].list_operands := arguments_operand;
- call_instruction^.operands[2].length := parsed_call^.count;
-
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- if procedure_info^.procedure_type^.return_type = nil then
- call_instruction^.operands[3].kind := ElnaTacKind.ignore
- else
- elna_tac_make_variable(operand, symbol_table, procedure_info^.procedure_type^.return_type);
- elna_tac_instruction_set_op(call_instruction, 3u, operand)
- end
- else
- call_instruction^.operands[3].kind := ElnaTacKind.ignore
- end;
-
- argument_entry := parsed_call^.arguments;
- while argument_entry <> nil & i < parsed_call^.count do
- elna_tac_binary_expression(instructions, argument_entry^.expression, symbol_table, arguments_operand + i);
- argument_entry := argument_entry^.next;
- i := i + 1u
- end;
- elna_list_append(instructions, cast(call_instruction: ^ElnaListNode))
-return
-
-proc elna_tac_goto_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeGotoStatement)
-var
- instruction: ^ElnaTacInstruction
-begin
- instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
- elna_tac_instruction_set_label(instruction, 1u, parser_node^.label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_label_declaration(instructions: ^ElnaList; parser_node: ^ElnaTreeLabelDeclaration)
-var
- result: ^ElnaTacInstruction
-begin
- result := elna_tac_instruction_create(ElnaTacOperator.label);
- elna_tac_instruction_set_label(result, 1u, parser_node^.label);
- elna_list_append(instructions, cast(result: ^ElnaListNode))
-return
-
-proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression; operand: ^ElnaTacOperand)
-var
- enumeration_type: ^ElnaTypeEnumeration
- members: ^[]const Word8
- members_length: Word
- symbol_info: ^ElnaSymbolInfo
- type_info: ^ElnaSymbolTypeInfo
- counter: Word := 1u
- found: Bool := false
- aggregate_tree: ^ElnaTreeVariableExpression
-begin
- aggregate_tree := cast(field_access_expression^.aggregate: ^ElnaTreeVariableExpression);
- symbol_info := elna_symbol_table_lookup(symbol_table_global, aggregate_tree^.name);
-
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.type_info then
- type_info := cast(symbol_info: ^ElnaSymbolTypeInfo);
- if type_info^._type^.kind = ElnaTypeKind.enumeration then
- enumeration_type := cast(type_info^._type: ^ElnaTypeEnumeration);
- members := enumeration_type^.members;
- members_length := enumeration_type^.length;
-
- while members_length > 0u & ~found do
- if members^ = field_access_expression^.field then
- found := true;
- operand^.kind := ElnaTacKind.constant;
- operand^.constant := counter;
- operand^.length := 4u;
- operand^.name := "";
- operand^.list_operands := nil
- else
- members_length := members_length - 1u;
- members := members + 1u;
- counter := counter + 1u
- end
- end
- end
- end
-return
-
-proc elna_tac_dereference_expression(instructions: ^ElnaList; dereference_expression: ^ElnaTreeDereferenceExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- load_instruction: ^ElnaTacInstruction
- operand_result: ElnaTacOperandResult
- intermediate: ElnaTacOperand
-begin
- elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @operand_result, operand);
-
- if operand_result.kind = ElnaTacOperandType.dereferenced_pointer then
- intermediate := operand^;
- elna_tac_make_variable(operand, symbol_table, word_type);
-
- load_instruction := elna_tac_instruction_create(ElnaTacOperator.load);
- elna_tac_instruction_set_op(load_instruction, 1u, @intermediate);
- elna_tac_instruction_set_op(load_instruction, 2u, operand);
- elna_list_append(instructions, cast(load_instruction: ^ElnaListNode))
- elsif operand_result.kind = ElnaTacOperandType.sub_object then
- intermediate := operand^;
- elna_tac_make_variable(operand, symbol_table, word_type);
-
- load_instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset);
- elna_tac_instruction_set_op(load_instruction, 1u, @intermediate);
- elna_tac_instruction_set_const(load_instruction, 2u, operand_result.offset, 4u);
- elna_tac_instruction_set_op(load_instruction, 3u, operand);
- elna_list_append(instructions, cast(load_instruction: ^ElnaListNode))
- end
-return
-
-proc elna_tac_field_access_expression(instructions: ^ElnaList; field_access_expression: ^ElnaTreeFieldAccessExpression;
- symbol_table: ^ElnaSymbolTable; operand_result: ^ElnaTacOperandResult; operand: ^ElnaTacOperand)
-var
- field_type: ^ElnaType
- instruction: ^ElnaTacInstruction
- designator_base: ^ElnaTreeExpression
- aggregate_type: ^ElnaTypeRecord
- field_count: Word
- current_field: ^ElnaTypeField
- field_offset: Word := 0u
- base: ElnaTacOperand
- found: Bool := false
-begin
- designator_base := field_access_expression^.aggregate;
- aggregate_type := cast(designator_base^.type_decoration: ^ElnaTypeRecord);
-
- elna_tac_designator(instructions, designator_base, symbol_table, operand_result, @base);
-
- if aggregate_type <> nil & aggregate_type^.kind = ElnaTypeKind._record then
- field_count := aggregate_type^.length;
- current_field := aggregate_type^.members;
-
- while field_count > 0u & ~found do
- if current_field^.name = field_access_expression^.field then
- found := true
- else
- field_type := current_field^.field_type;
- field_count := field_count - 1u;
- field_offset := field_offset + field_type^.size;
- current_field := current_field + 1u
- end
- end
- end;
-
- if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then
- elna_tac_make_variable(operand, symbol_table, word_type);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.add);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_const(instruction, 2u, field_offset, 4u);
- elna_tac_instruction_set_op(instruction, 3u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif operand_result^.kind = ElnaTacOperandType.sub_object then
- operand^ := base;
- operand_result^.offset := operand_result^.offset + field_offset
- else
- operand^ := base;
- operand_result^.kind := ElnaTacOperandType.sub_object;
- operand_result^.offset := field_offset
- end
-return
-
-proc elna_tac_array_access_expression(instructions: ^ElnaList; array_access_expression: ^ElnaTreeArrayAccessExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
- operand_result: ElnaTacOperandResult
- inter_operand: ElnaTacOperand
- index_operand: ElnaTacOperand
- aggregate_type: ^ElnaTypeArray
- designator_base: ^ElnaTreeExpression
- element_type: ^ElnaType
- elem_size: Word := 1u
-begin
- designator_base := array_access_expression^.array;
- if designator_base^.type_decoration <> nil & designator_base^.type_decoration^.kind = ElnaTypeKind.array then
- aggregate_type := cast(designator_base^.type_decoration: ^ElnaTypeArray);
- element_type := aggregate_type^.base;
- if element_type <> nil then
- elem_size := element_type^.size
- end
- end;
-
- elna_tac_binary_expression(instructions, array_access_expression^.index, symbol_table, @inter_operand);
- elna_tac_make_variable(@index_operand, symbol_table, word_type);
-
- (* In Elna arrays are 1-based, subtract 1 for 0-based index *)
- instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
- elna_tac_instruction_set_op(instruction, 1u, @inter_operand);
- elna_tac_instruction_set_const(instruction, 2u, 1u, 4u);
- elna_tac_instruction_set_op(instruction, 3u, @index_operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- elna_tac_designator(instructions, array_access_expression^.array,
- symbol_table, @operand_result, @inter_operand);
- elna_tac_make_variable(operand, symbol_table, word_type);
- elna_tac_copy_address(instructions, @operand_result, @inter_operand, operand);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.add_ptr);
- elna_tac_instruction_set_op(instruction, 1u, operand);
- elna_tac_instruction_set_op(instruction, 2u, @index_operand);
- elna_tac_instruction_set_const(instruction, 3u, elem_size, 4u);
- elna_tac_instruction_set_op(instruction, 4u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_designator(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable;
- operand_result: ^ElnaTacOperandResult; operand: ^ElnaTacOperand)
-var
- field_access_expression: ^ElnaTreeFieldAccessExpression
- designator_base: ^ElnaTreeExpression
-begin
- operand_result^.kind := ElnaTacOperandType.plain_object;
- operand_result^.offset := 0u;
-
- case parser_node^.kind of
- ElnaTreeKind.dereference_expression:
- elna_tac_dereference_expression(instructions, cast(parser_node: ^ElnaTreeDereferenceExpression), symbol_table, operand);
- operand_result^.kind := ElnaTacOperandType.dereferenced_pointer
- | ElnaTreeKind.field_access_expression:
- field_access_expression := cast(parser_node: ^ElnaTreeFieldAccessExpression);
- designator_base := field_access_expression^.aggregate;
-
- if designator_base^.type_decoration = nil then
- elna_tac_enumeration_value(field_access_expression, operand)
- else
- elna_tac_field_access_expression(instructions, field_access_expression, symbol_table, operand_result, operand)
- end
- | ElnaTreeKind.array_access_expression:
- elna_tac_array_access_expression(instructions, cast(parser_node: ^ElnaTreeArrayAccessExpression), symbol_table, operand);
- operand_result^.kind := ElnaTacOperandType.dereferenced_pointer
- | ElnaTreeKind.call:
- elna_tac_call(instructions, cast(parser_node: ^ElnaTreeCall), symbol_table, operand)
- else
- elna_tac_simple_expression(instructions, parser_node, symbol_table, operand)
- end
-return
-
-proc elna_tac_assign_statement(instructions: ^ElnaList; parser_tree: ^ElnaTreeAssignStatement; symbol_table: ^ElnaSymbolTable)
-var
- operand_result: ElnaTacOperandResult
- instruction: ^ElnaTacInstruction
- assignment_operand: ElnaTacOperand
- assignee: ElnaTacOperand
-begin
- elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @operand_result, @assignee);
- elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand);
-
- if operand_result.kind = ElnaTacOperandType.dereferenced_pointer then
- instruction := elna_tac_instruction_create(ElnaTacOperator.store);
- elna_tac_instruction_set_op(instruction, 1u, @assignment_operand);
- elna_tac_instruction_set_op(instruction, 2u, @assignee)
- elsif operand_result.kind = ElnaTacOperandType.sub_object then
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
- elna_tac_instruction_set_op(instruction, 1u, @assignment_operand);
- elna_tac_instruction_set_op(instruction, 2u, @assignee);
- elna_tac_instruction_set_const(instruction, 3u, operand_result.offset, 4u)
- else
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
- elna_tac_instruction_set_op(instruction, 1u, @assignment_operand);
- elna_tac_instruction_set_op(instruction, 2u, @assignee)
- end;
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_return_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeReturnStatement; symbol_table: ^ElnaSymbolTable)
-var
- instruction: ^ElnaTacInstruction
- operand: ElnaTacOperand
-begin
- instruction := elna_tac_instruction_create(ElnaTacOperator._return);
- if parser_node^.returned <> nil then
- elna_tac_binary_expression(instructions, parser_node^.returned, symbol_table, @operand);
- elna_tac_instruction_set_op(instruction, 1u, @operand)
- else
- instruction^.operands[1].kind := ElnaTacKind.ignore
- end;
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_conditional_statements(instructions: ^ElnaList; parser_node: ^ElnaTreeConditionalStatements;
- after_end_label: []const Word8; symbol_table: ^ElnaSymbolTable)
-var
- condition_label: []const Word8
- instruction: ^ElnaTacInstruction
- operand: ElnaTacOperand
-begin
- elna_tac_binary_expression(instructions, parser_node^.condition, symbol_table, @operand);
- condition_label := elna_tac_label();
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.jump_if_zero);
- elna_tac_instruction_set_op(instruction, 1u, @operand);
- elna_tac_instruction_set_label(instruction, 2u, condition_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- elna_tac_statements(instructions, parser_node^.statements, symbol_table);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
- elna_tac_instruction_set_label(instruction, 1u, after_end_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.label);
- elna_tac_instruction_set_label(instruction, 1u, condition_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_if_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeIfStatement; symbol_table: ^ElnaSymbolTable)
-var
- current_node: ^ElnaTreeConditionalStatements
- after_end_label: []const Word8
- instruction: ^ElnaTacInstruction
-begin
- after_end_label := elna_tac_label();
- current_node := parser_node^.conditionals;
-
- while current_node <> nil do
- elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table);
- current_node := current_node^.next
- end;
-
- if parser_node^._else <> nil then
- elna_tac_statements(instructions, parser_node^._else, symbol_table)
- end;
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.label);
- elna_tac_instruction_set_label(instruction, 1u, after_end_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable)
-var
- operand: ElnaTacOperand
- call_statement: ^ElnaTreeCallStatement
-begin
- case parser_node^.kind of
- ElnaTreeKind.goto_statement:
- elna_tac_goto_statement(instructions, cast(parser_node: ^ElnaTreeGotoStatement))
- | ElnaTreeKind.if_statement:
- elna_tac_if_statement(instructions, cast(parser_node: ^ElnaTreeIfStatement), symbol_table)
- | ElnaTreeKind.return_statement:
- elna_tac_return_statement(instructions, cast(parser_node: ^ElnaTreeReturnStatement), symbol_table)
- | ElnaTreeKind.label_declaration:
- elna_tac_label_declaration(instructions, cast(parser_node: ^ElnaTreeLabelDeclaration))
- | ElnaTreeKind.call_statement:
- call_statement := cast(parser_node: ^ElnaTreeCallStatement);
- elna_tac_call(instructions, call_statement^.call, symbol_table, @operand)
- | ElnaTreeKind.assign_statement:
- elna_tac_assign_statement(instructions, cast(parser_node: ^ElnaTreeAssignStatement), symbol_table)
- else
- end
-return
-
-proc elna_tac_statements(instructions: ^ElnaList; current_statement: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable)
-var
- current: ^ElnaTreeStatement
-begin
- current := current_statement;
- while current <> nil do
- elna_tac_statement(instructions, current, symbol_table);
- current := current^.next
- end
-return
-
-proc elna_tac_parameters(ast_list: ^ElnaTreeDeclaration; parameter_count: ^Word) -> ^[]const Word8
-var
- ast_parameter: ^ElnaTreeDeclaration
- parameter_list: ^[]const Word8
- count: Word := 0u
- i: Word := 0u
-begin
- ast_parameter := ast_list;
- while ast_parameter <> nil do
- count := count + 1u;
- ast_parameter := ast_parameter^.next
- end;
- parameter_count^ := count;
-
- parameter_list := malloc#[[]const Word8](count * #size([]const Word8));
- ast_parameter := ast_list;
- while i < count do
- (parameter_list + i)^ := ast_parameter^.name;
- i := i + 1u;
- ast_parameter := ast_parameter^.next
- end
-return parameter_list
-
-proc elna_tac_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration) -> ^ElnaTacProcedure
-var
- symbol_info: ^ElnaSymbolInfo
- procedure_info: ^ElnaSymbolProcedureInfo
- result: ^ElnaTacProcedure
- parameter_count: Word := 0u
-begin
- result := malloc#[ElnaTacProcedure](#size(ElnaTacProcedure));
- result^.next := nil;
- elna_list_initialize(@result^.body);
- result^.name := parser_node^.name;
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- result^.symbol_table := procedure_info^.symbol_table
- else
- result^.symbol_table := symbol_table_global
- end;
-
- result^.parameters := elna_tac_parameters(parser_node^.parameters, @parameter_count);
- result^.count := parameter_count;
- pseudo_counter := 0u;
-
- elna_tac_statements(@result^.body, parser_node^.body, result^.symbol_table)
-return result
-
-proc elna_tac_procedures(parser_node: ^ElnaTreeProcedureDeclaration) -> ^ElnaTacProcedure
-var
- result: ^ElnaTacProcedure
- current_procedure: ^ElnaTacProcedure := nil
- first_procedure: ^ElnaTacProcedure := nil
- current_node: ^ElnaTreeProcedureDeclaration
-begin
- current_node := parser_node;
- while current_node <> nil do
- if ~current_node^.is_extern then
- result := elna_tac_procedure_declaration(current_node);
- if first_procedure = nil then
- first_procedure := result
- else
- current_procedure^.next := result
- end;
- current_procedure := result
- end;
- current_node := cast(current_node^.next: ^ElnaTreeProcedureDeclaration)
- end
-return first_procedure
-
-proc elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration) -> ^ElnaTacStaticVariable
-var
- result: ^ElnaTacStaticVariable
- symbol_info: ^ElnaSymbolInfo
- temp_info: ^ElnaSymbolTemporaryInfo
-begin
- result := malloc#[ElnaTacStaticVariable](#size(ElnaTacStaticVariable));
- result^.next := nil;
- result^.name := parser_tree^.name;
- result^.size := 4u;
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_tree^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.temporary_info then
- temp_info := cast(symbol_info: ^ElnaSymbolTemporaryInfo);
- if temp_info^.variable_type <> nil then
- result^.size := temp_info^.variable_type^.size
- end
- end
-return result
-
-proc elna_tac_var_part(parser_node: ^ElnaTreeDeclaration) -> ^ElnaTacStaticVariable
-var
- node: ^ElnaTacStaticVariable
- current_variable: ^ElnaTacStaticVariable := nil
- first_variable: ^ElnaTacStaticVariable := nil
- current_node: ^ElnaTreeDeclaration
-begin
- current_node := parser_node;
- while current_node <> nil do
- node := elna_tac_variable_declaration(cast(current_node: ^ElnaTreeVariableDeclaration));
- if first_variable = nil then
- first_variable := node
- else
- current_variable^.next := node
- end;
- current_variable := node;
- current_node := current_node^.next
- end
-return first_variable
-
-proc elna_tac_program_body(parser_node: ^ElnaTreeStatement) -> ^ElnaTacProcedure
-var
- result: ^ElnaTacProcedure
- symbol_info: ^ElnaSymbolInfo
- procedure_info: ^ElnaSymbolProcedureInfo
-begin
- result := malloc#[ElnaTacProcedure](#size(ElnaTacProcedure));
- result^.next := nil;
- elna_list_initialize(@result^.body);
- result^.name := "main";
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, result^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- result^.symbol_table := procedure_info^.symbol_table
- else
- result^.symbol_table := symbol_table_global
- end;
-
- result^.parameters := nil;
- result^.count := 0u;
- pseudo_counter := 0u;
-
- elna_tac_statements(@result^.body, parser_node, result^.symbol_table)
-return result
-
-proc elna_tac_module_declaration*(parser_node: ^ElnaTreeModuleDeclaration) -> ^ElnaInstructionModule
-var
- result: ^ElnaInstructionModule
- last_proc: ^ElnaTacProcedure
- body_proc: ^ElnaTacProcedure
-begin
- result := malloc#[ElnaInstructionModule](#size(ElnaInstructionModule));
- result^.strings := module_strings_first;
- result^.data := elna_tac_var_part(parser_node^.globals);
- result^.code := elna_tac_procedures(parser_node^.procedures);
-
- if parser_node^.body <> nil then
- body_proc := elna_tac_program_body(parser_node^.body);
- if result^.code = nil then
- result^.code := body_proc
- else
- last_proc := result^.code;
- while last_proc^.next <> nil do
- last_proc := last_proc^.next
- end;
- last_proc^.next := body_proc
- end
- end;
- result^.strings := module_strings_first
-return result
-
-end.