From 11935ac271c2670d160a9eb0977d086634a96fec Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Sat, 27 Jun 2026 09:18:55 +0800 Subject: [PATCH 1/2] llvm: add intrinsic call bindings --- IRBindings.cpp | 9 +++++++++ IRBindings.h | 4 ++++ ir.go | 15 +++++++++++++++ ir_test.go | 30 ++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/IRBindings.cpp b/IRBindings.cpp index be0a466..89a3caf 100644 --- a/IRBindings.cpp +++ b/IRBindings.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -85,3 +86,11 @@ LLVMValueRef LLVMGoGetInlineAsm(LLVMTypeRef Ty, char *AsmString, IsAlignStack, Dialect, CanThrow); } + +LLVMValueRef LLVMGoBuildIntrinsicCall(LLVMBuilderRef B, LLVMTypeRef RetTy, + unsigned ID, LLVMValueRef *Args, + unsigned Count, const char *Name) { + return wrap(unwrap(B)->CreateIntrinsic( + unwrap(RetTy), static_cast(ID), + ArrayRef(unwrap(Args), Count), nullptr, Name)); +} diff --git a/IRBindings.h b/IRBindings.h index 80552de..5428be7 100644 --- a/IRBindings.h +++ b/IRBindings.h @@ -55,6 +55,10 @@ LLVMValueRef LLVMGoGetInlineAsm(LLVMTypeRef Ty, char *AsmString, LLVMBool IsAlignStack, LLVMInlineAsmDialect Dialect, LLVMBool CanThrow); +LLVMValueRef LLVMGoBuildIntrinsicCall(LLVMBuilderRef B, LLVMTypeRef RetTy, + unsigned ID, LLVMValueRef *Args, + unsigned Count, const char *Name); + #ifdef __cplusplus } #endif diff --git a/ir.go b/ir.go index 3925053..f93d080 100644 --- a/ir.go +++ b/ir.go @@ -385,6 +385,13 @@ func MDKindID(name string) (id int) { return } +func LookupIntrinsicID(name string) (id int) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + id = int(C.LLVMLookupIntrinsicID(cname, C.size_t(len(name)))) + return +} + //------------------------------------------------------------------------- // llvm.Attribute //------------------------------------------------------------------------- @@ -1955,6 +1962,14 @@ func (b Builder) CreateCall(t Type, fn Value, args []Value, name string) (v Valu return } +func (b Builder) CreateIntrinsic(ret Type, id int, args []Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(args) + v.C = C.LLVMGoBuildIntrinsicCall(b.C, ret.C, C.unsigned(id), ptr, nvals, cname) + return +} + func (b Builder) CreateSelect(ifv, thenv, elsev Value, name string) (v Value) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) diff --git a/ir_test.go b/ir_test.go index a912aec..0f03b52 100644 --- a/ir_test.go +++ b/ir_test.go @@ -145,6 +145,36 @@ func TestDebugLoc(t *testing.T) { } } +func TestIntrinsicBindings(t *testing.T) { + ctx := NewContext() + mod := ctx.NewModule("") + defer mod.Dispose() + + memsetID := LookupIntrinsicID("llvm.memset") + if memsetID == 0 { + t.Fatal("could not look up llvm.memset intrinsic") + } + ptrTy := PointerType(ctx.Int8Type(), 0) + fnTy := FunctionType(ctx.VoidType(), []Type{ptrTy}, false) + fn := AddFunction(mod, "use_memset", fnTy) + builder := ctx.NewBuilder() + defer builder.Dispose() + builder.SetInsertPointAtEnd(ctx.AddBasicBlock(fn, "entry")) + call := builder.CreateIntrinsic(ctx.VoidType(), memsetID, []Value{ + fn.Param(0), + ConstInt(ctx.Int8Type(), 0, false), + ConstInt(ctx.Int64Type(), 8, false), + ConstInt(ctx.Int1Type(), 0, false), + }, "") + builder.CreateRetVoid() + if got := call.CalledValue().Name(); got != "llvm.memset.p0.i64" { + t.Fatalf("got intrinsic callee %q, want llvm.memset.p0.i64", got) + } + if err := VerifyModule(mod, ReturnStatusAction); err != nil { + t.Fatalf("module with intrinsic call should verify: %v", err) + } +} + func TestSubtypes(t *testing.T) { cont := NewContext() defer cont.Dispose() From b1a749c0c32f197c0670c054d0eb7fc7a1573b8e Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Sat, 27 Jun 2026 13:38:58 +0800 Subject: [PATCH 2/2] llvm: support intrinsic calls on older LLVM --- IRBindings.cpp | 23 ++++++++++++++++++++--- ir_test.go | 4 ++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/IRBindings.cpp b/IRBindings.cpp index 89a3caf..4788c92 100644 --- a/IRBindings.cpp +++ b/IRBindings.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "IRBindings.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -90,7 +91,23 @@ LLVMValueRef LLVMGoGetInlineAsm(LLVMTypeRef Ty, char *AsmString, LLVMValueRef LLVMGoBuildIntrinsicCall(LLVMBuilderRef B, LLVMTypeRef RetTy, unsigned ID, LLVMValueRef *Args, unsigned Count, const char *Name) { - return wrap(unwrap(B)->CreateIntrinsic( - unwrap(RetTy), static_cast(ID), - ArrayRef(unwrap(Args), Count), nullptr, Name)); + Intrinsic::ID IntrinsicID = static_cast(ID); + ArrayRef UnwrappedArgs(unwrap(Args), Count); + SmallVector ParamTys; + SmallVector OverloadTys; + SmallVector Infos; + + ParamTys.reserve(Count); + for (Value *Arg : UnwrappedArgs) + ParamTys.push_back(Arg->getType()); + + FunctionType *FTy = FunctionType::get(unwrap(RetTy), ParamTys, false); + Intrinsic::getIntrinsicInfoTableEntries(IntrinsicID, Infos); + ArrayRef InfoRef(Infos); + if (Intrinsic::matchIntrinsicSignature(FTy, InfoRef, OverloadTys) != + Intrinsic::MatchIntrinsicTypes_Match) + return nullptr; + + return wrap(unwrap(B)->CreateIntrinsic(IntrinsicID, OverloadTys, + UnwrappedArgs, nullptr, Name)); } diff --git a/ir_test.go b/ir_test.go index 0f03b52..0a9d5e8 100644 --- a/ir_test.go +++ b/ir_test.go @@ -167,8 +167,8 @@ func TestIntrinsicBindings(t *testing.T) { ConstInt(ctx.Int1Type(), 0, false), }, "") builder.CreateRetVoid() - if got := call.CalledValue().Name(); got != "llvm.memset.p0.i64" { - t.Fatalf("got intrinsic callee %q, want llvm.memset.p0.i64", got) + if got := call.CalledValue().IntrinsicID(); got != memsetID { + t.Fatalf("got intrinsic ID %d, want %d", got, memsetID) } if err := VerifyModule(mod, ReturnStatusAction); err != nil { t.Fatalf("module with intrinsic call should verify: %v", err)