From 036e38442bd7b5fa18063e06e79f1076dbc31516 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 9 Aug 2026 21:55:36 +0100 Subject: [PATCH] Begin work on `lb_emit_asm_template_call` --- src/llvm_backend.cpp | 1 + src/llvm_backend.hpp | 2 ++ src/llvm_backend_asm.cpp | 43 +++++++++++++++++++++++++++++++++++++++ src/llvm_backend_proc.cpp | 24 ++++++++++++++++++---- src/parser.cpp | 2 +- 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/llvm_backend_asm.cpp diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8b1474fb6..0021d5b76 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -29,6 +29,7 @@ #include "llvm_backend_expr.cpp" #include "llvm_backend_stmt.cpp" #include "llvm_backend_proc.cpp" +#include "llvm_backend_asm.cpp" gb_internal String get_default_microarchitecture() { String default_march = str_lit("generic"); diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index a38f67d86..563f854d7 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -467,6 +467,8 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t); gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x); +gb_internal lbValue lb_emit_asm_template_call(lbProcedure *p, Entity *entity, Array const &args); + gb_internal void lb_emit_jump(lbProcedure *p, lbBlock *target_block); gb_internal void lb_emit_if(lbProcedure *p, lbValue cond, lbBlock *true_block, lbBlock *false_block); gb_internal void lb_start_block(lbProcedure *p, lbBlock *b); diff --git a/src/llvm_backend_asm.cpp b/src/llvm_backend_asm.cpp new file mode 100644 index 000000000..ad8e54a0e --- /dev/null +++ b/src/llvm_backend_asm.cpp @@ -0,0 +1,43 @@ +gb_internal lbValue lb_emit_asm_template_call(lbProcedure *p, Entity *entity, Array const &args) { + GB_ASSERT(entity->kind == Entity_AsmTemplate); + + // GB_PANIC("TODO(bill): lb_emit_asm_template_call"); + gbString asm_string = gb_string_make(heap_allocator(), ""); + gbString constraints = gb_string_make(heap_allocator(), ""); + + auto *ate = &entity->AsmTemplate; + GB_ASSERT(ate->node->kind == Ast_AsmTemplate); + auto *node = &ate->node->AsmTemplate; + + for_array(i, node->instructions) { + auto *instruction = node->instructions[i]; + gb_unused(instruction); + } + // asm_string = gb_string_appendc(asm_string, "lock cmpxchg16b $3"); + // asm_string = gb_string_appendc(asm_string, "\\0A\\09"); + // asm_string = gb_string_appendc(asm_string, "setz $2"); + + // constraints = gb_string_appendc(constraints, "*m,={ax},={dx},=r,{ax},{dx},{bx},{cx},~{cc},~{memory}"); + + Type *proc_type = base_type(entity->type); + GB_ASSERT(proc_type->kind == Type_Proc); + + LLVMTypeRef llvm_type = lb_type_internal_for_procedures_raw(p->module, proc_type); + gb_printf_err("%s\n", LLVMPrintTypeToString(llvm_type)); + + LLVMValueRef fn = LLVMGetInlineAsm(llvm_type, asm_string, gb_string_length(asm_string), + constraints, gb_string_length(constraints), + entity->AsmTemplate.has_side_effects, + entity->AsmTemplate.is_align_stack, + LLVMInlineAsmDialectATT, /*CanThrow*/false); + + LLVMValueRef *llvm_args = gb_alloc_array(heap_allocator(), LLVMValueRef, args.count); + for_array(i, args) { + llvm_args[i] = args[i].value; + } + LLVMValueRef result = LLVMBuildCall2(p->builder, llvm_type, fn, llvm_args, cast(unsigned)args.count, ""); + Type *result_type = reduce_tuple_to_single_type(proc_type->Proc.results); + + gb_printf_err("%s\n", LLVMPrintValueToString(result)); + return {result, result_type}; +} \ No newline at end of file diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index b528980ec..607dafde2 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -5023,6 +5023,7 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbVal // NOTE(bill): Regular call lbValue value = {}; + Entity *asm_template = nullptr; if (proc_entity != nullptr) { if (proc_entity->flags & EntityFlag_Disabled) { @@ -5056,15 +5057,25 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbVal } } } + Type *proc_value_type = nullptr; if (is_objc_call) { value.type = proc_tv.type; + proc_value_type = value.type; } else if (value.value == nullptr) { - value = lb_build_expr(p, proc_expr); + Entity *found = entity_of_node(proc_expr); + if (found && found->kind == Entity_AsmTemplate) { + asm_template = found; + proc_value_type = asm_template->type; + } else { + value = lb_build_expr(p, proc_expr); + proc_value_type = value.type; + } } - GB_ASSERT(value.value != nullptr || is_objc_call); - Type *proc_type_ = base_type(value.type); + + GB_ASSERT(value.value != nullptr || is_objc_call || asm_template != nullptr); + Type *proc_type_ = base_type(proc_value_type); GB_ASSERT(proc_type_->kind == Type_Proc); TypeProc *pt = &proc_type_->Proc; @@ -5283,6 +5294,11 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbVal } } - return lb_emit_call(p, value, call_args, inlining, tailing, sret_dst); + if (asm_template != nullptr) { + GB_ASSERT(value.value == nullptr); + return lb_emit_asm_template_call(p, asm_template, call_args); + } else { + return lb_emit_call(p, value, call_args, inlining, tailing, sret_dst); + } } diff --git a/src/parser.cpp b/src/parser.cpp index 39d87669d..10d2e7cdd 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2547,7 +2547,7 @@ gb_internal Ast *parse_asm_signature(AstFile *f, Token asm_token) { expect_token(f, Token_OpenParen); f->expr_level += 1; - params = parse_field_list(f, nullptr, FieldFlag_Signature, Token_CloseParen, false, false); + params = parse_field_list(f, nullptr, FieldFlag_Signature, Token_CloseParen, false, true); if (file_allow_newline(f)) { skip_possible_newline(f); }