From 317894b6e7b8acfe7d32e7bfd3a75f0fc9e8319e Mon Sep 17 00:00:00 2001
From: alperenunal <alpernunl@gmail.com>
Date: Tue, 27 Dec 2022 00:10:36 +0300
Subject: [PATCH 1/2] Add LLVM intrinsic funtions

---
 ir.go | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/ir.go b/ir.go
index 25631d3..7bd0e22 100644
--- a/ir.go
+++ b/ir.go
@@ -1180,6 +1180,40 @@ func (v Value) AddTargetDependentFunctionAttr(attr, value string) {
 func (v Value) SetPersonality(p Value) {
 	C.LLVMSetPersonalityFn(v.C, p.C)
 }
+func IntrinsicID(name string) (id uint) {
+	cname := C.CString(name)
+	defer C.free(unsafe.Pointer(cname))
+	id = uint(C.LLVMLookupIntrinsicID(cname, C.size_t(len(name))))
+	return
+}
+func IsIntrinsicOverloaded(id uint) bool {
+	return C.LLVMIntrinsicIsOverloaded(C.unsigned(id)) != 0
+}
+func IntrinsicName(id uint) string {
+	length := C.size_t(0)
+	cname := C.LLVMIntrinsicGetName(C.unsigned(id), &length)
+	return C.GoStringN(cname, C.int(length))
+}
+func (c Context) IntrinsicType(id uint, paramTypes []Type) (t Type) {
+	t.C = C.LLVMIntrinsicGetType(c.C, C.unsigned(id), llvmTypeRefPtr(&paramTypes[0]), C.size_t(len(paramTypes)))
+	return
+}
+func (c Module) InsertIntrinsic(id uint, paramTypes []Type) (v Value) {
+	var pt *C.LLVMTypeRef
+	if paramTypes == nil {
+		pt = nil
+	} else {
+		pt = llvmTypeRefPtr(&paramTypes[0])
+	}
+	v.C = C.LLVMGetIntrinsicDeclaration(c.C, C.unsigned(id), pt, C.size_t(len(paramTypes)))
+	return
+}
+func (c Module) CopyOverloadedName(id uint, paramTypes []Type) string {
+	lenght := C.size_t(0)
+	cname := C.LLVMIntrinsicCopyOverloadedName2(c.C, C.unsigned(id), llvmTypeRefPtr(&paramTypes[0]), C.size_t(len(paramTypes)), &lenght)
+	defer C.free(unsafe.Pointer(cname))
+	return C.GoStringN(cname, C.int(lenght))
+}
 
 // Operations on parameters
 func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) }

From 1044c105e209acfde3a6a086487203ecb60389c4 Mon Sep 17 00:00:00 2001
From: alperenunal <alpernunl@gmail.com>
Date: Thu, 12 Jan 2023 14:43:59 +0300
Subject: [PATCH 2/2] Add LLVM intrinsic functions

---
 ir.go | 97 ++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 63 insertions(+), 34 deletions(-)

diff --git a/ir.go b/ir.go
index 7bd0e22..13e7771 100644
--- a/ir.go
+++ b/ir.go
@@ -76,6 +76,7 @@ type (
 	FloatPredicate      C.LLVMRealPredicate
 	LandingPadClause    C.LLVMLandingPadClauseTy
 	InlineAsmDialect    C.LLVMInlineAsmDialect
+	Intrinsic           C.unsigned
 )
 
 func (c Context) IsNil() bool        { return c.C == nil }
@@ -1180,40 +1181,6 @@ func (v Value) AddTargetDependentFunctionAttr(attr, value string) {
 func (v Value) SetPersonality(p Value) {
 	C.LLVMSetPersonalityFn(v.C, p.C)
 }
-func IntrinsicID(name string) (id uint) {
-	cname := C.CString(name)
-	defer C.free(unsafe.Pointer(cname))
-	id = uint(C.LLVMLookupIntrinsicID(cname, C.size_t(len(name))))
-	return
-}
-func IsIntrinsicOverloaded(id uint) bool {
-	return C.LLVMIntrinsicIsOverloaded(C.unsigned(id)) != 0
-}
-func IntrinsicName(id uint) string {
-	length := C.size_t(0)
-	cname := C.LLVMIntrinsicGetName(C.unsigned(id), &length)
-	return C.GoStringN(cname, C.int(length))
-}
-func (c Context) IntrinsicType(id uint, paramTypes []Type) (t Type) {
-	t.C = C.LLVMIntrinsicGetType(c.C, C.unsigned(id), llvmTypeRefPtr(&paramTypes[0]), C.size_t(len(paramTypes)))
-	return
-}
-func (c Module) InsertIntrinsic(id uint, paramTypes []Type) (v Value) {
-	var pt *C.LLVMTypeRef
-	if paramTypes == nil {
-		pt = nil
-	} else {
-		pt = llvmTypeRefPtr(&paramTypes[0])
-	}
-	v.C = C.LLVMGetIntrinsicDeclaration(c.C, C.unsigned(id), pt, C.size_t(len(paramTypes)))
-	return
-}
-func (c Module) CopyOverloadedName(id uint, paramTypes []Type) string {
-	lenght := C.size_t(0)
-	cname := C.LLVMIntrinsicCopyOverloadedName2(c.C, C.unsigned(id), llvmTypeRefPtr(&paramTypes[0]), C.size_t(len(paramTypes)), &lenght)
-	defer C.free(unsafe.Pointer(cname))
-	return C.GoStringN(cname, C.int(lenght))
-}
 
 // Operations on parameters
 func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) }
@@ -2060,3 +2027,65 @@ func (pm PassManager) FinalizeFunc() bool { return C.LLVMFinalizeFunctionPassMan
 // the module provider.
 // See llvm::PassManagerBase::~PassManagerBase.
 func (pm PassManager) Dispose() { C.LLVMDisposePassManager(pm.C) }
+
+//-------------------------------------------------------------------------
+// llvm.Intrinsic
+//-------------------------------------------------------------------------
+
+// Obtain the intrinsic ID number which matches the given function name.
+// See llvm::Function::lookupIntrinsicID.
+func IntrinsicID(name string) (in Intrinsic) {
+	cname := C.CString(name)
+	defer C.free(unsafe.Pointer(cname))
+	in = Intrinsic(C.LLVMLookupIntrinsicID(cname, C.size_t(len(name))))
+	return
+}
+
+// Obtain if the intrinsic identified by the given ID is overloaded.
+// See llvm::Intrinsic::isOverloaded
+func (in Intrinsic) IsOverloaded() bool {
+	return C.LLVMIntrinsicIsOverloaded(C.unsigned(in)) != 0
+}
+
+// Retrieves the name of an intrinsic.
+// See llvm::Intrinsic::getName
+func (in Intrinsic) GetName() string {
+	length := C.size_t(0)
+	cname := C.LLVMIntrinsicGetName(C.unsigned(in), &length)
+	return C.GoStringN(cname, C.int(length))
+}
+
+// Retrieves the type of an intrinsic. For overloaded intrinsics, parameter types must be provided to uniquely identify an overload.
+// See llvm::Intrinsic::getType
+func (c Context) GetIntrinsicType(in Intrinsic, paramTypes []Type) (t Type) {
+	var pt *C.LLVMTypeRef
+	if paramTypes != nil {
+		pt = llvmTypeRefPtr(&paramTypes[0])
+	}
+	t.C = C.LLVMIntrinsicGetType(c.C, C.unsigned(in), pt, C.size_t(len(paramTypes)))
+	return
+}
+
+// Create or insert the declaration of an intrinsic. For overloaded intrinsics, parameter types must be provided to uniquely identify an overload.
+// See llvm::Intrinsic::getDeclaration
+func (m Module) GetIntrinsic(in Intrinsic, paramTypes []Type) (v Value) {
+	var pt *C.LLVMTypeRef
+	if paramTypes != nil {
+		pt = llvmTypeRefPtr(&paramTypes[0])
+	}
+	v.C = C.LLVMGetIntrinsicDeclaration(m.C, C.unsigned(in), pt, C.size_t(len(paramTypes)))
+	return
+}
+
+// Copies the name of an overloaded intrinsic identified by a given list of parameter types.
+// See llvm::Intrinsic::getName
+func (m Module) CopyOverloadedName(in Intrinsic, paramTypes []Type) string {
+	var pt *C.LLVMTypeRef
+	if paramTypes != nil {
+		pt = llvmTypeRefPtr(&paramTypes[0])
+	}
+	lenght := C.size_t(0)
+	cname := C.LLVMIntrinsicCopyOverloadedName2(m.C, C.unsigned(in), pt, C.size_t(len(paramTypes)), &lenght)
+	defer C.free(unsafe.Pointer(cname))
+	return C.GoStringN(cname, C.int(lenght))
+}