aboutsummaryrefslogtreecommitdiff
path: root/source/qbe.elna
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-09 09:55:53 +0200
committerEugen Wissner <belka@caraus.de>2026-10-09 10:33:53 +0200
commit244449004fb62adbfd43b81e8dfce7500ca4a7e4 (patch)
treeb115946fc1efc2edc0de71a4e6d7cce2c50f39f2 /source/qbe.elna
parent994e6c95929ad9551901d86617e4678920f8f357 (diff)
downloadelna-244449004fb62adbfd43b81e8dfce7500ca4a7e4.tar.gz
Move export mark after the generic parameters
Diffstat (limited to 'source/qbe.elna')
-rw-r--r--source/qbe.elna635
1 files changed, 0 insertions, 635 deletions
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.