From 1d17b26ace6a5e6ebbc488911fe5528fae92aad5 Mon Sep 17 00:00:00 2001 From: rj45 Date: Sun, 27 Aug 2023 06:25:52 -0700 Subject: [PATCH 1/6] Add support for opaque pointers and structs --- ir.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ir.go b/ir.go index 28595b1..fb6f611 100644 --- a/ir.go +++ b/ir.go @@ -665,6 +665,7 @@ func (t Type) StructSetBody(elementTypes []Type, packed bool) { } func (t Type) IsStructPacked() bool { return C.LLVMIsPackedStruct(t.C) != 0 } +func (t Type) IsStructOpaque() bool { return C.LLVMIsOpaqueStruct(t.C) != 0 } func (t Type) StructElementTypesCount() int { return int(C.LLVMCountStructElementTypes(t.C)) } func (t Type) StructElementTypes() []Type { out := make([]Type, t.StructElementTypesCount()) @@ -676,7 +677,12 @@ func (t Type) StructElementTypes() []Type { // Operations on array, pointer, and vector types (sequence types) func (t Type) Subtypes() (ret []Type) { - ret = make([]Type, C.LLVMGetNumContainedTypes(t.C)) + num := C.LLVMGetNumContainedTypes(t.C) + if num == 0 { + // prevent a crash at &ret[0] if there are no subtypes + return nil + } + ret = make([]Type, num) C.LLVMGetSubtypes(t.C, llvmTypeRefPtr(&ret[0])) return } @@ -694,6 +700,7 @@ func VectorType(elementType Type, elementCount int) (t Type) { return } +func (t Type) IsPointerOpaque() bool { return C.LLVMPointerTypeIsOpaque(t.C) != 0 } func (t Type) ElementType() (rt Type) { rt.C = C.LLVMGetElementType(t.C); return } func (t Type) ArrayLength() int { return int(C.LLVMGetArrayLength(t.C)) } func (t Type) PointerAddressSpace() int { return int(C.LLVMGetPointerAddressSpace(t.C)) } From c9ce16188b302ceeb045efeb754105cf68f4c7f3 Mon Sep 17 00:00:00 2001 From: rj45 Date: Sun, 27 Aug 2023 09:01:41 -0700 Subject: [PATCH 2/6] Add backport for checking opaque pointer types --- backports.cpp | 13 +++++++++++++ backports.h | 13 +++++++++++++ ir.go | 25 +++++++++++++++++++++---- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/backports.cpp b/backports.cpp index c3d80a1..f08ff18 100644 --- a/backports.cpp +++ b/backports.cpp @@ -48,3 +48,16 @@ LLVMMemoryBufferRef LLVMGoWriteThinLTOBitcodeToMemoryBuffer(LLVMModuleRef M) { #endif return llvm::wrap(llvm::MemoryBuffer::getMemBufferCopy(OS.str()).release()); } + +#if LLVM_VERSION_MAJOR < 15 + +// This is backported because version 14 supports opaque +// pointers but I presume if you try to access the element +// type it will crash. So this backport prevents that by +// allowing to check if the pointer is opaque before trying +// to access the element type. +LLVMBool LLVMPointerTypeIsOpaque(LLVMTypeRef Ty) { + return llvm::unwrap(Ty)->isOpaquePointerTy(); +} + +#endif \ No newline at end of file diff --git a/backports.h b/backports.h index d5b9a9c..aff8fe9 100644 --- a/backports.h +++ b/backports.h @@ -14,6 +14,19 @@ LLVMMemoryBufferRef LLVMGoWriteThinLTOBitcodeToMemoryBuffer(LLVMModuleRef M); LLVMMetadataRef LLVMGoDIBuilderCreateExpression(LLVMDIBuilderRef Builder, uint64_t *Addr, size_t Length); +#if LLVM_VERSION_MAJOR < 15 +/** + * Determine whether a pointer is opaque. + * + * True if this is an instance of an opaque PointerType. + * + * @see llvm::Type::isOpaquePointerTy() + */ +LLVMBool LLVMPointerTypeIsOpaque(LLVMTypeRef Ty); + +#endif + + #ifdef __cplusplus } #endif /* defined(__cplusplus) */ diff --git a/ir.go b/ir.go index fb6f611..c03ae75 100644 --- a/ir.go +++ b/ir.go @@ -19,8 +19,10 @@ package llvm #include */ import "C" -import "unsafe" -import "errors" +import ( + "errors" + "unsafe" +) type ( // We use these weird structs here because *Ref types are pointers and @@ -700,8 +702,23 @@ func VectorType(elementType Type, elementCount int) (t Type) { return } -func (t Type) IsPointerOpaque() bool { return C.LLVMPointerTypeIsOpaque(t.C) != 0 } -func (t Type) ElementType() (rt Type) { rt.C = C.LLVMGetElementType(t.C); return } +// IsPointerOpaque checks if the pointer is an opaque pointer. +// +// see llvm::Type::isOpaquePointerTy() +func (t Type) IsPointerOpaque() bool { return C.LLVMPointerTypeIsOpaque(t.C) != 0 } + +// ElementType returns the type of the element for arrays, pointers and vectors. +// +// see llvm::SequentialType::getElementType() +func (t Type) ElementType() (rt Type) { + if t.IsPointerOpaque() { + // avoid segfault + return Type{} + } + rt.C = C.LLVMGetElementType(t.C) + return +} + func (t Type) ArrayLength() int { return int(C.LLVMGetArrayLength(t.C)) } func (t Type) PointerAddressSpace() int { return int(C.LLVMGetPointerAddressSpace(t.C)) } func (t Type) VectorSize() int { return int(C.LLVMGetVectorSize(t.C)) } From f4f14b25de227a222a2dccbe1ed6a536f227285f Mon Sep 17 00:00:00 2001 From: rj45 Date: Sun, 27 Aug 2023 09:04:08 -0700 Subject: [PATCH 3/6] Checking for opaque pointer in ElementType() is perhaps not safe --- ir.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ir.go b/ir.go index c03ae75..e58962a 100644 --- a/ir.go +++ b/ir.go @@ -711,10 +711,6 @@ func (t Type) IsPointerOpaque() bool { return C.LLVMPointerTypeIsOpaque(t.C) != // // see llvm::SequentialType::getElementType() func (t Type) ElementType() (rt Type) { - if t.IsPointerOpaque() { - // avoid segfault - return Type{} - } rt.C = C.LLVMGetElementType(t.C) return } From b1eb97c064c968eedf21a161d1e99f9ae2686f8f Mon Sep 17 00:00:00 2001 From: rj45 Date: Sun, 27 Aug 2023 09:10:35 -0700 Subject: [PATCH 4/6] Forgot to include backports --- ir.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ir.go b/ir.go index e58962a..73b96a2 100644 --- a/ir.go +++ b/ir.go @@ -16,6 +16,7 @@ package llvm #include "llvm-c/Core.h" #include "llvm-c/Comdat.h" #include "IRBindings.h" +#include "backports.h" #include */ import "C" From 6e3693a0fa0effd83313e42c653e3c354b03c029 Mon Sep 17 00:00:00 2001 From: rj45 Date: Sat, 2 Sep 2023 05:01:57 -0700 Subject: [PATCH 5/6] Maybe fix CI? --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cad9ca9..7c024db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,6 +41,7 @@ jobs: - name: Install LLVM run: | brew update + brew install --overwrite python@3.11 brew install llvm@16 - name: Test LLVM 16 run: From 85891f2f8f3c107e9dbcd9b91187c0438e9f8551 Mon Sep 17 00:00:00 2001 From: rj45 Date: Sat, 2 Sep 2023 05:10:20 -0700 Subject: [PATCH 6/6] Revert "Maybe fix CI?" This reverts commit 69314f823f8c7facab407a9afb2481159e036b72. --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7c024db..cad9ca9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,6 @@ jobs: - name: Install LLVM run: | brew update - brew install --overwrite python@3.11 brew install llvm@16 - name: Test LLVM 16 run: