From 244449004fb62adbfd43b81e8dfce7500ca4a7e4 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 9 Oct 2026 09:55:53 +0200 Subject: Move export mark after the generic parameters --- source/qbe.elna | 635 -------------------------------------------------------- 1 file changed, 635 deletions(-) delete mode 100644 source/qbe.elna (limited to 'source/qbe.elna') diff --git a/source/qbe.elna b/source/qbe.elna deleted file mode 100644 index 47eac88..0000000 --- a/source/qbe.elna +++ /dev/null @@ -1,635 +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, tac - -var - qbe_unique_id: Word := 0u - -proc qbe_write_slice(file: ^FILE; text: []const Word8) -begin - fwrite#[Word8](text.ptr, 1u, text.length, file) -return - -proc qbe_write_str(file: ^FILE; str: ^const Word8) -begin - fwrite#[Word8](str, 1u, strlen(str), file) -return - -proc qbe_write_word(file: ^FILE; val: Word) -var - buf: [32]Word8 - len: Int -begin - len := sprintf(@buf[1], "%u\0".ptr, val); - fwrite#[Word8](@buf[1], 1u, cast(len: Word), file) -return - -proc is_global(globals: ^ElnaTacStaticVariable; name: []const Word8) -> Bool -var - current: ^ElnaTacStaticVariable - found: Bool := false -begin - current := globals; - while current <> nil & ~found do - if current^.name = name then - found := true - else - current := current^.next - end - end -return found - -proc is_string_constant(strings: ^ElnaTacStringConstant; name: []const Word8) -> Bool -var - current: ^ElnaTacStringConstant - found: Bool := false -begin - current := strings; - while current <> nil & ~found do - if current^.name = name then - found := true - else - current := current^.next - end - end -return found - -proc is_pointer_type(_type: ^ElnaType) -> Bool -var - result: Bool := false -begin - if _type <> nil then - if _type^.kind = ElnaTypeKind.pointer then - result := true - elsif _type = pointer_type then - result := true - end - end -return result - -proc get_procedure_return_type(proc_name: []const Word8) -> ^ElnaType -var - symbol_info: ^ElnaSymbolInfo - procedure_info: ^ElnaSymbolProcedureInfo - result: ^ElnaType := nil -begin - symbol_info := elna_symbol_table_lookup(symbol_table_global, proc_name); - if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then - procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo); - if procedure_info^.procedure_type <> nil then - result := procedure_info^.procedure_type^.return_type - end - end -return result - -proc get_param_type(sym_table: ^ElnaSymbolTable; param_name: []const Word8) -> ^ElnaType -var - symbol_info: ^ElnaSymbolInfo - temp_info: ^ElnaSymbolTemporaryInfo - result: ^ElnaType := nil -begin - symbol_info := elna_symbol_table_lookup(sym_table, param_name); - if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.temporary_info then - temp_info := cast(symbol_info: ^ElnaSymbolTemporaryInfo); - result := temp_info^.variable_type - end -return result - -proc is_pointer_operand(op: ^ElnaTacOperand; sym_table: ^ElnaSymbolTable; - globals: ^ElnaTacStaticVariable; strings: ^ElnaTacStringConstant) -> Bool -var - var_type: ^ElnaType - result: Bool := false -begin - if op^.kind = ElnaTacKind.variable then - if is_global(globals, op^.name) or is_string_constant(strings, op^.name) then - result := true - else - var_type := get_param_type(sym_table, op^.name); - if is_pointer_type(var_type) then - result := true - end - end - end -return result - -proc qbe_emit_operand(file: ^FILE; op: ^ElnaTacOperand; - globals: ^ElnaTacStaticVariable; strings: ^ElnaTacStringConstant) -begin - case op^.kind of - ElnaTacKind.constant: - qbe_write_word(file, op^.constant) - | ElnaTacKind.variable: - if is_global(globals, op^.name) or is_string_constant(strings, op^.name) then - qbe_write_str(file, "$\0".ptr) - else - qbe_write_str(file, "%\0".ptr) - end; - qbe_write_slice(file, op^.name) - | ElnaTacKind.label: - qbe_write_str(file, "@\0".ptr); - qbe_write_slice(file, op^.name) - else - end -return - -proc var_needs_stack_alloc(instructions: ^ElnaList; sym_table: ^ElnaSymbolTable; name: []const Word8) -> Bool -var - node: ^ElnaListNode - inst: ^ElnaTacInstruction - var_type: ^ElnaType - result: Bool := false -begin - var_type := get_param_type(sym_table, name); - if var_type <> nil then - if var_type^.kind = ElnaTypeKind._record or var_type^.kind = ElnaTypeKind.array then - result := true - end - end; - - node := instructions^.first; - while node <> nil & ~result do - inst := cast(node: ^ElnaTacInstruction); - if inst^.operator = ElnaTacOperator.get_address & inst^.operands[1].name = name then - result := true - elsif inst^.operator = ElnaTacOperator.copy_to_offset & inst^.operands[2].name = name then - result := true - elsif inst^.operator = ElnaTacOperator.copy_from_offset & inst^.operands[1].name = name then - result := true - end; - node := node^.next - end -return result - -proc qbe_emit_procedure(file: ^FILE; proc_node: ^ElnaTacProcedure; - globals: ^ElnaTacStaticVariable; strings: ^ElnaTacStringConstant) -var - node: ^ElnaListNode - inst: ^ElnaTacInstruction - ret_type: ^ElnaType - param_idx: Word := 0u - param_name: []const Word8 - param_type: ^ElnaType - entry: ^ElnaSymbolEntry - temp_info: ^ElnaSymbolTemporaryInfo - sym_idx: Word := 0u - alloc_size: Word - last_operator: ElnaTacOperator := ElnaTacOperator.nop - tid: Word - arg_i: Word - arg_op: ^ElnaTacOperand - callee_ret: ^ElnaType - scaled: Word -begin - qbe_write_str(file, "export function \0".ptr); - ret_type := get_procedure_return_type(proc_node^.name); - - if proc_node^.name = "main" then - qbe_write_str(file, "w \0".ptr) - elsif ret_type <> nil then - if ret_type = bool_type then - qbe_write_str(file, "w \0".ptr) - else - qbe_write_str(file, "l \0".ptr) - end - end; - - qbe_write_str(file, "$\0".ptr); - qbe_write_slice(file, proc_node^.name); - qbe_write_str(file, "(\0".ptr); - - while param_idx < proc_node^.count do - param_name := (proc_node^.parameters + param_idx)^; - param_type := get_param_type(proc_node^.symbol_table, param_name); - if param_type = bool_type then - qbe_write_str(file, "w %\0".ptr) - else - qbe_write_str(file, "l %\0".ptr) - end; - qbe_write_slice(file, param_name); - if param_idx + 1u < proc_node^.count then - qbe_write_str(file, ", \0".ptr) - end; - param_idx := param_idx + 1u - end; - - qbe_write_str(file, ") {\n@start\n\0".ptr); - - (* Stack allocate variables needing memory address *) - if proc_node^.symbol_table <> nil then - while sym_idx < proc_node^.symbol_table^.count do - entry := proc_node^.symbol_table^.symbols + sym_idx; - if entry^.name.length > 0u & entry^.symbol_info <> nil then - if entry^.symbol_info^.kind = ElnaSymbolInfoKind.temporary_info then - temp_info := cast(entry^.symbol_info: ^ElnaSymbolTemporaryInfo); - if var_needs_stack_alloc(@proc_node^.body, proc_node^.symbol_table, entry^.name) then - alloc_size := 8u; - if temp_info^.variable_type <> nil & temp_info^.variable_type^.size > 8u then - alloc_size := (temp_info^.variable_type^.size + 7u) / 8u * 8u - end; - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, entry^.name); - qbe_write_str(file, " =l alloc8 \0".ptr); - qbe_write_word(file, alloc_size); - qbe_write_str(file, "\n\0".ptr) - end - end - end; - sym_idx := sym_idx + 1u - end - end; - - (* Emit TAC instructions *) - node := proc_node^.body.first; - while node <> nil do - inst := cast(node: ^ElnaTacInstruction); - last_operator := inst^.operator; - - case inst^.operator of - ElnaTacOperator.get_address: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[2].name); - qbe_write_str(file, " =l copy \0".ptr); - if is_global(globals, inst^.operands[1].name) or is_string_constant(strings, inst^.operands[1].name) then - qbe_write_str(file, "$\0".ptr) - else - qbe_write_str(file, "%\0".ptr) - end; - qbe_write_slice(file, inst^.operands[1].name); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.copy: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[2].name); - qbe_write_str(file, " =l copy \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.add: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l add \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.subtract: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l sub \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.multiply: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l mul \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.divide: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l div \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.remainder: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l rem \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator._or: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l or \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator._xor: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l xor \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.and: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l and \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.equal: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =w ceql \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.not_equal: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =w cnew \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.less_than: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =w csltl \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.greater_than: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =w csgtl \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.less_or_equal: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =w cslel \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.greater_or_equal: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =w csgel \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.negate: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[2].name); - qbe_write_str(file, " =l neg \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.complement: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[2].name); - qbe_write_str(file, " =l xor \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", -1\n\0".ptr) - | ElnaTacOperator.load: - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[2].name); - qbe_write_str(file, " =l loadl \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.store: - qbe_write_str(file, "\tstorel \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.copy_to_offset: - if inst^.operands[3].constant = 0u then - qbe_write_str(file, "\tstorel \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr) - else - qbe_unique_id := qbe_unique_id + 1u; - tid := qbe_unique_id; - qbe_write_str(file, "\t%qbe_off_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, " =l add \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_write_word(file, inst^.operands[3].constant); - qbe_write_str(file, "\n\tstorel \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", %qbe_off_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, "\n\0".ptr) - end - | ElnaTacOperator.copy_from_offset: - if inst^.operands[2].constant = 0u then - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l loadl \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, "\n\0".ptr) - else - qbe_unique_id := qbe_unique_id + 1u; - tid := qbe_unique_id; - qbe_write_str(file, "\t%qbe_off_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, " =l add \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_write_word(file, inst^.operands[2].constant); - qbe_write_str(file, "\n\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - qbe_write_str(file, " =l loadl %qbe_off_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, "\n\0".ptr) - end - | ElnaTacOperator.add_ptr: - qbe_unique_id := qbe_unique_id + 1u; - tid := qbe_unique_id; - if inst^.operands[2].kind = ElnaTacKind.constant then - if inst^.operands[3].constant = 1u then - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[4].name); - qbe_write_str(file, " =l add \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_write_word(file, inst^.operands[2].constant); - qbe_write_str(file, "\n\0".ptr) - else - scaled := inst^.operands[2].constant * inst^.operands[3].constant; - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[4].name); - qbe_write_str(file, " =l add \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", \0".ptr); - qbe_write_word(file, scaled); - qbe_write_str(file, "\n\0".ptr) - end - else - qbe_write_str(file, "\t%qbe_ext_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, " =l extuw \0".ptr); - qbe_emit_operand(file, @inst^.operands[2], globals, strings); - qbe_write_str(file, "\n\0".ptr); - - if inst^.operands[3].constant = 1u then - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[4].name); - qbe_write_str(file, " =l add \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", %qbe_ext_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, "\n\0".ptr) - else - qbe_write_str(file, "\t%qbe_s_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, " =l mul %qbe_ext_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, ", \0".ptr); - qbe_write_word(file, inst^.operands[3].constant); - qbe_write_str(file, "\n\t%\0".ptr); - qbe_write_slice(file, inst^.operands[4].name); - qbe_write_str(file, " =l add \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", %qbe_s_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, "\n\0".ptr) - end - end - | ElnaTacOperator.proc_call: - callee_ret := get_procedure_return_type(inst^.operands[1].name); - if inst^.operands[3].kind = ElnaTacKind.ignore then - qbe_write_str(file, "\tcall $\0".ptr) - else - qbe_write_str(file, "\t%\0".ptr); - qbe_write_slice(file, inst^.operands[3].name); - if callee_ret = bool_type then - qbe_write_str(file, " =w call $\0".ptr) - else - qbe_write_str(file, " =l call $\0".ptr) - end - end; - qbe_write_slice(file, inst^.operands[1].name); - qbe_write_str(file, "(\0".ptr); - - arg_i := 0u; - while arg_i < inst^.operands[2].length do - arg_op := inst^.operands[2].list_operands + arg_i; - qbe_write_str(file, "l \0".ptr); - qbe_emit_operand(file, arg_op, globals, strings); - if arg_i + 1u < inst^.operands[2].length then - qbe_write_str(file, ", \0".ptr) - end; - arg_i := arg_i + 1u - end; - qbe_write_str(file, ")\n\0".ptr) - | ElnaTacOperator.jump: - qbe_write_str(file, "\tjmp @\0".ptr); - qbe_write_slice(file, inst^.operands[1].name); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.jump_if_zero: - qbe_unique_id := qbe_unique_id + 1u; - tid := qbe_unique_id; - qbe_write_str(file, "\tjnz \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", @qbe_ft_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, ", @\0".ptr); - qbe_write_slice(file, inst^.operands[2].name); - qbe_write_str(file, "\n@qbe_ft_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.jump_if_not_zero: - qbe_unique_id := qbe_unique_id + 1u; - tid := qbe_unique_id; - qbe_write_str(file, "\tjnz \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, ", @\0".ptr); - qbe_write_slice(file, inst^.operands[2].name); - qbe_write_str(file, ", @qbe_ft_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, "\n@qbe_ft_\0".ptr); - qbe_write_word(file, tid); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator.label: - qbe_write_str(file, "@\0".ptr); - qbe_write_slice(file, inst^.operands[1].name); - qbe_write_str(file, "\n\0".ptr) - | ElnaTacOperator._return: - if inst^.operands[1].kind = ElnaTacKind.ignore then - qbe_write_str(file, "\tret\n\0".ptr) - else - qbe_write_str(file, "\tret \0".ptr); - qbe_emit_operand(file, @inst^.operands[1], globals, strings); - qbe_write_str(file, "\n\0".ptr) - end - else - end; - node := node^.next - end; - - (* Function terminator if not terminated *) - if last_operator <> ElnaTacOperator._return & last_operator <> ElnaTacOperator.jump then - if proc_node^.name = "main" then - qbe_write_str(file, "\tret 0\n\0".ptr) - elsif ret_type = nil then - qbe_write_str(file, "\tret\n\0".ptr) - else - qbe_write_str(file, "\tret 0\n\0".ptr) - end - end; - - qbe_write_str(file, "}\n\n\0".ptr) -return - -proc elna_qbe_emit*(instruction_module: ^ElnaInstructionModule; out_file: ^FILE) -var - current_string: ^ElnaTacStringConstant - current_global: ^ElnaTacStaticVariable - current_proc: ^ElnaTacProcedure - i: Word - byte_val: Word -begin - (* Emit strings *) - current_string := instruction_module^.strings; - while current_string <> nil do - qbe_write_str(out_file, "data $\0".ptr); - qbe_write_slice(out_file, current_string^.name); - qbe_write_str(out_file, " = { \0".ptr); - - i := 0u; - while i < current_string^.value.length do - qbe_write_str(out_file, "b \0".ptr); - byte_val := cast((current_string^.value.ptr + i)^: Word); - qbe_write_word(out_file, byte_val); - qbe_write_str(out_file, ", \0".ptr); - i := i + 1u - end; - qbe_write_str(out_file, "b 0 }\n\0".ptr); - - current_string := current_string^.next - end; - - (* Emit global data *) - current_global := instruction_module^.data; - while current_global <> nil do - qbe_write_str(out_file, "export data $\0".ptr); - qbe_write_slice(out_file, current_global^.name); - qbe_write_str(out_file, " = { z \0".ptr); - qbe_write_word(out_file, current_global^.size); - qbe_write_str(out_file, " }\n\0".ptr); - - current_global := current_global^.next - end; - - (* Emit procedures *) - current_proc := instruction_module^.code; - while current_proc <> nil do - qbe_emit_procedure(out_file, current_proc, instruction_module^.data, instruction_module^.strings); - current_proc := current_proc^.next - end -return - -end. -- cgit v1.2.3