Begin work on lb_emit_asm_template_call

This commit is contained in:
gingerBill
2026-08-09 21:55:36 +01:00
parent 25ce7e87de
commit 036e38442b
5 changed files with 67 additions and 5 deletions

View File

@@ -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");

View File

@@ -467,6 +467,8 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> 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<lbValue> 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);

43
src/llvm_backend_asm.cpp Normal file
View File

@@ -0,0 +1,43 @@
gb_internal lbValue lb_emit_asm_template_call(lbProcedure *p, Entity *entity, Array<lbValue> 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};
}

View File

@@ -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);
}
}

View File

@@ -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);
}