From 5874309ec5ad2e05ddd2ddba11217d5ef5c0589a Mon Sep 17 00:00:00 2001 From: rj45 Date: Wed, 16 Aug 2023 08:30:29 -0700 Subject: [PATCH 1/5] Add getting strings from string constants --- ir.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ir.go b/ir.go index 28595b1..4b62c31 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 @@ -910,6 +912,18 @@ func ConstVector(scalarConstVals []Value, packed bool) (v Value) { return } +// IsConstantString checks if the constant is an array of i8. +func (v Value) IsConstantString() bool { + return C.LLVMIsConstantString(v.C) != 0 +} + +// ConstGetAsString will return the string contained in a constant. +func (v Value) ConstGetAsString() string { + length := C.ulong(0) + cstr := C.LLVMGetAsString(v.C, &length) + return C.GoStringN(cstr, C.int(length)) +} + // Constant expressions func (v Value) Opcode() Opcode { return Opcode(C.LLVMGetConstOpcode(v.C)) } func (v Value) InstructionOpcode() Opcode { return Opcode(C.LLVMGetInstructionOpcode(v.C)) } From 95543fc98db17100a20b365ba18dfffc32b29e9a Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 18 Sep 2023 19:24:53 +0200 Subject: [PATCH 2/5] Remove old `// +build` lines These aren't needed anymore. --- llvm_config_darwin_llvm14.go | 1 - llvm_config_darwin_llvm15.go | 1 - llvm_config_darwin_llvm16.go | 1 - llvm_config_linux_llvm14.go | 1 - llvm_config_linux_llvm15.go | 1 - llvm_config_linux_llvm16.go | 1 - llvm_dep.go | 1 - 7 files changed, 7 deletions(-) diff --git a/llvm_config_darwin_llvm14.go b/llvm_config_darwin_llvm14.go index 8b9ffda..0e7ed76 100644 --- a/llvm_config_darwin_llvm14.go +++ b/llvm_config_darwin_llvm14.go @@ -1,5 +1,4 @@ //go:build !byollvm && darwin && llvm14 -// +build !byollvm,darwin,llvm14 package llvm diff --git a/llvm_config_darwin_llvm15.go b/llvm_config_darwin_llvm15.go index f384ee4..31ad7cc 100644 --- a/llvm_config_darwin_llvm15.go +++ b/llvm_config_darwin_llvm15.go @@ -1,5 +1,4 @@ //go:build !byollvm && darwin && !llvm14 && !llvm16 -// +build !byollvm,darwin,!llvm14,!llvm16 package llvm diff --git a/llvm_config_darwin_llvm16.go b/llvm_config_darwin_llvm16.go index 58c1761..fab59da 100644 --- a/llvm_config_darwin_llvm16.go +++ b/llvm_config_darwin_llvm16.go @@ -1,5 +1,4 @@ //go:build !byollvm && darwin && llvm16 -// +build !byollvm,darwin,llvm16 package llvm diff --git a/llvm_config_linux_llvm14.go b/llvm_config_linux_llvm14.go index 06f5ea0..3f91a53 100644 --- a/llvm_config_linux_llvm14.go +++ b/llvm_config_linux_llvm14.go @@ -1,5 +1,4 @@ //go:build !byollvm && linux && llvm14 -// +build !byollvm,linux,llvm14 package llvm diff --git a/llvm_config_linux_llvm15.go b/llvm_config_linux_llvm15.go index 0e28025..6900449 100644 --- a/llvm_config_linux_llvm15.go +++ b/llvm_config_linux_llvm15.go @@ -1,5 +1,4 @@ //go:build !byollvm && linux && !llvm14 && !llvm16 -// +build !byollvm,linux,!llvm14,!llvm16 package llvm diff --git a/llvm_config_linux_llvm16.go b/llvm_config_linux_llvm16.go index 239ee5e..4208cf4 100644 --- a/llvm_config_linux_llvm16.go +++ b/llvm_config_linux_llvm16.go @@ -1,5 +1,4 @@ //go:build !byollvm && linux && llvm16 -// +build !byollvm,linux,llvm16 package llvm diff --git a/llvm_dep.go b/llvm_dep.go index eeee96a..cdce01b 100644 --- a/llvm_dep.go +++ b/llvm_dep.go @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// //go:build !byollvm -// +build !byollvm package llvm From b1e2b88150a7c569d76daa523b9d0fdb3e231404 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 18 Sep 2023 19:33:50 +0200 Subject: [PATCH 3/5] Default to LLVM 16 --- .github/workflows/test.yml | 12 ++++++------ llvm_config_darwin_llvm15.go | 2 +- llvm_config_darwin_llvm16.go | 2 +- llvm_config_linux_llvm15.go | 2 +- llvm_config_linux_llvm16.go | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cad9ca9..0d19cd0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,9 +30,6 @@ jobs: - name: Test LLVM 15 run: go test -v -tags=llvm15 - - name: Test default LLVM - run: - go test -v test-macos-llvm-16: runs-on: macos-latest steps: @@ -45,6 +42,9 @@ jobs: - name: Test LLVM 16 run: go test -v -tags=llvm16 + - name: Test default LLVM + run: + go test -v test-linux-llvm-14: runs-on: ubuntu-20.04 steps: @@ -73,9 +73,6 @@ jobs: - name: Test LLVM 15 run: go test -v -tags=llvm15 - - name: Test default LLVM - run: - go test -v test-linux-llvm-16: runs-on: ubuntu-20.04 steps: @@ -90,3 +87,6 @@ jobs: - name: Test LLVM 16 run: go test -v -tags=llvm16 + - name: Test default LLVM + run: + go test -v diff --git a/llvm_config_darwin_llvm15.go b/llvm_config_darwin_llvm15.go index 31ad7cc..fbf5fe0 100644 --- a/llvm_config_darwin_llvm15.go +++ b/llvm_config_darwin_llvm15.go @@ -1,4 +1,4 @@ -//go:build !byollvm && darwin && !llvm14 && !llvm16 +//go:build !byollvm && darwin && llvm15 package llvm diff --git a/llvm_config_darwin_llvm16.go b/llvm_config_darwin_llvm16.go index fab59da..a2f0147 100644 --- a/llvm_config_darwin_llvm16.go +++ b/llvm_config_darwin_llvm16.go @@ -1,4 +1,4 @@ -//go:build !byollvm && darwin && llvm16 +//go:build !byollvm && darwin && !llvm14 && !llvm15 package llvm diff --git a/llvm_config_linux_llvm15.go b/llvm_config_linux_llvm15.go index 6900449..607ed7e 100644 --- a/llvm_config_linux_llvm15.go +++ b/llvm_config_linux_llvm15.go @@ -1,4 +1,4 @@ -//go:build !byollvm && linux && !llvm14 && !llvm16 +//go:build !byollvm && linux && llvm15 package llvm diff --git a/llvm_config_linux_llvm16.go b/llvm_config_linux_llvm16.go index 4208cf4..bc37463 100644 --- a/llvm_config_linux_llvm16.go +++ b/llvm_config_linux_llvm16.go @@ -1,4 +1,4 @@ -//go:build !byollvm && linux && llvm16 +//go:build !byollvm && linux && !llvm14 && !llvm15 package llvm From 9edb6403d0bcf79769f41abc46aa5769fc5e48e3 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 18 Sep 2023 20:39:30 +0200 Subject: [PATCH 4/5] Fix type mismatch on Windows It's C.size_t and not C.ulong (apparently size_t is a ulonglong on Windows). --- ir.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ir.go b/ir.go index 4b62c31..1027889 100644 --- a/ir.go +++ b/ir.go @@ -919,7 +919,7 @@ func (v Value) IsConstantString() bool { // ConstGetAsString will return the string contained in a constant. func (v Value) ConstGetAsString() string { - length := C.ulong(0) + length := C.size_t(0) cstr := C.LLVMGetAsString(v.C, &length) return C.GoStringN(cstr, C.int(length)) } From ffd05344e2b353f43b49f50b6170ebf41797f40d Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 18 Sep 2023 23:16:30 +0200 Subject: [PATCH 5/5] Remove functions/methods that work on the global context The global context should almost never be used, but it's very easy to use accidentally. Therefore, I'd like to remove all convenience functions that use the global context. All functionality that got removed is still accessible as methods on llvm.Context, and the global context can be obtained using llvm.GlobalContext(). So no actual functionality is lost, just the very easy to misuse "convenience" functions. --- bitreader.go | 25 ------------------------- executionengine_test.go | 19 ++++++++++--------- ir.go | 30 +----------------------------- ir_test.go | 10 +++++----- 4 files changed, 16 insertions(+), 68 deletions(-) diff --git a/bitreader.go b/bitreader.go index 2ed3218..cb88bad 100644 --- a/bitreader.go +++ b/bitreader.go @@ -24,31 +24,6 @@ import ( "unsafe" ) -// ParseBitcodeFile parses the LLVM IR (bitcode) in the file with the -// specified name, and returns a new LLVM module. -func ParseBitcodeFile(name string) (Module, error) { - var buf C.LLVMMemoryBufferRef - var errmsg *C.char - var cfilename *C.char = C.CString(name) - defer C.free(unsafe.Pointer(cfilename)) - result := C.LLVMCreateMemoryBufferWithContentsOfFile(cfilename, &buf, &errmsg) - if result != 0 { - err := errors.New(C.GoString(errmsg)) - C.free(unsafe.Pointer(errmsg)) - return Module{}, err - } - defer C.LLVMDisposeMemoryBuffer(buf) - - var m Module - if C.LLVMParseBitcode2(buf, &m.C) == 0 { - return m, nil - } - - err := errors.New(C.GoString(errmsg)) - C.free(unsafe.Pointer(errmsg)) - return Module{}, err -} - // ParseBitcodeFile parses the LLVM IR (bitcode) in the file with the specified // name, and returns a new LLVM module. func (c Context) ParseBitcodeFile(name string) (Module, error) { diff --git a/executionengine_test.go b/executionengine_test.go index df3e815..86b1dc9 100644 --- a/executionengine_test.go +++ b/executionengine_test.go @@ -21,10 +21,11 @@ func TestFactorial(t *testing.T) { InitializeNativeTarget() InitializeNativeAsmPrinter() - mod := NewModule("fac_module") + ctx := NewContext() + mod := ctx.NewModule("fac_module") - fac_args := []Type{Int32Type()} - fac_type := FunctionType(Int32Type(), fac_args, false) + fac_args := []Type{ctx.Int32Type()} + fac_type := FunctionType(ctx.Int32Type(), fac_args, false) fac := AddFunction(mod, "fac", fac_type) fac.SetFunctionCallConv(CCallConv) n := fac.Param(0) @@ -34,26 +35,26 @@ func TestFactorial(t *testing.T) { iffalse := AddBasicBlock(fac, "iffalse") end := AddBasicBlock(fac, "end") - builder := NewBuilder() + builder := ctx.NewBuilder() defer builder.Dispose() builder.SetInsertPointAtEnd(entry) - If := builder.CreateICmp(IntEQ, n, ConstInt(Int32Type(), 0, false), "cmptmp") + If := builder.CreateICmp(IntEQ, n, ConstInt(ctx.Int32Type(), 0, false), "cmptmp") builder.CreateCondBr(If, iftrue, iffalse) builder.SetInsertPointAtEnd(iftrue) - res_iftrue := ConstInt(Int32Type(), 1, false) + res_iftrue := ConstInt(ctx.Int32Type(), 1, false) builder.CreateBr(end) builder.SetInsertPointAtEnd(iffalse) - n_minus := builder.CreateSub(n, ConstInt(Int32Type(), 1, false), "subtmp") + n_minus := builder.CreateSub(n, ConstInt(ctx.Int32Type(), 1, false), "subtmp") call_fac_args := []Value{n_minus} call_fac := builder.CreateCall(fac_type, fac, call_fac_args, "calltmp") res_iffalse := builder.CreateMul(n, call_fac, "multmp") builder.CreateBr(end) builder.SetInsertPointAtEnd(end) - res := builder.CreatePHI(Int32Type(), "result") + res := builder.CreatePHI(ctx.Int32Type(), "result") phi_vals := []Value{res_iftrue, res_iffalse} phi_blocks := []BasicBlock{iftrue, iffalse} res.AddIncoming(phi_vals, phi_blocks) @@ -87,7 +88,7 @@ func TestFactorial(t *testing.T) { pass.AddCFGSimplificationPass() pass.Run(mod) - exec_args := []GenericValue{NewGenericValueFromInt(Int32Type(), 10, false)} + exec_args := []GenericValue{NewGenericValueFromInt(ctx.Int32Type(), 10, false)} exec_res := engine.RunFunction(fac, exec_args) var fac10 uint64 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 if exec_res.Int(false) != fac10 { diff --git a/ir.go b/ir.go index 1027889..c6bc6de 100644 --- a/ir.go +++ b/ir.go @@ -448,13 +448,6 @@ func (a Attribute) IsString() bool { // Create and destroy modules. // See llvm::Module::Module. -func NewModule(name string) (m Module) { - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) - m.C = C.LLVMModuleCreateWithName(cname) - return -} - func (c Context) NewModule(name string) (m Module) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -563,17 +556,6 @@ func (c Context) IntType(numbits int) (t Type) { return } -func Int1Type() (t Type) { t.C = C.LLVMInt1Type(); return } -func Int8Type() (t Type) { t.C = C.LLVMInt8Type(); return } -func Int16Type() (t Type) { t.C = C.LLVMInt16Type(); return } -func Int32Type() (t Type) { t.C = C.LLVMInt32Type(); return } -func Int64Type() (t Type) { t.C = C.LLVMInt64Type(); return } - -func IntType(numbits int) (t Type) { - t.C = C.LLVMIntType(C.unsigned(numbits)) - return -} - func (t Type) IntTypeWidth() int { return int(C.LLVMGetIntTypeWidth(t.C)) } @@ -585,12 +567,6 @@ func (c Context) X86FP80Type() (t Type) { t.C = C.LLVMX86FP80TypeInContext(c.C) func (c Context) FP128Type() (t Type) { t.C = C.LLVMFP128TypeInContext(c.C); return } func (c Context) PPCFP128Type() (t Type) { t.C = C.LLVMPPCFP128TypeInContext(c.C); return } -func FloatType() (t Type) { t.C = C.LLVMFloatType(); return } -func DoubleType() (t Type) { t.C = C.LLVMDoubleType(); return } -func X86FP80Type() (t Type) { t.C = C.LLVMX86FP80Type(); return } -func FP128Type() (t Type) { t.C = C.LLVMFP128Type(); return } -func PPCFP128Type() (t Type) { t.C = C.LLVMPPCFP128Type(); return } - // Operations on function types func FunctionType(returnType Type, paramTypes []Type, isVarArg bool) (t Type) { var pt *C.LLVMTypeRef @@ -706,9 +682,6 @@ func (c Context) VoidType() (t Type) { t.C = C.LLVMVoidTypeInContext(c.C); retu func (c Context) LabelType() (t Type) { t.C = C.LLVMLabelTypeInContext(c.C); return } func (c Context) TokenType() (t Type) { t.C = C.LLVMTokenTypeInContext(c.C); return } -func VoidType() (t Type) { t.C = C.LLVMVoidType(); return } -func LabelType() (t Type) { t.C = C.LLVMLabelType(); return } - //------------------------------------------------------------------------- // llvm.Value //------------------------------------------------------------------------- @@ -1363,7 +1336,6 @@ func (v Value) AllocatedType() (t Type) { t.C = C.LLVMGetAllocatedType(v.C); ret // exclusive means of building instructions using the C interface. func (c Context) NewBuilder() (b Builder) { b.C = C.LLVMCreateBuilderInContext(c.C); return } -func NewBuilder() (b Builder) { b.C = C.LLVMCreateBuilder(); return } func (b Builder) SetInsertPoint(block BasicBlock, instr Value) { C.LLVMPositionBuilder(b.C, block.C, instr.C) } @@ -1402,7 +1374,7 @@ func (b Builder) GetCurrentDebugLocation() (loc DebugLoc) { func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) } func (b Builder) InsertDeclare(module Module, storage Value, md Value) Value { f := module.NamedFunction("llvm.dbg.declare") - ftyp := FunctionType(VoidType(), []Type{storage.Type(), md.Type()}, false) + ftyp := FunctionType(module.Context().VoidType(), []Type{storage.Type(), md.Type()}, false) if f.IsNil() { f = AddFunction(module, "llvm.dbg.declare", ftyp) } diff --git a/ir_test.go b/ir_test.go index f0fae1e..57b306f 100644 --- a/ir_test.go +++ b/ir_test.go @@ -19,10 +19,11 @@ import ( ) func testAttribute(t *testing.T, name string) { - mod := NewModule("") + ctx := NewContext() + mod := ctx.NewModule("") defer mod.Dispose() - ftyp := FunctionType(VoidType(), nil, false) + ftyp := FunctionType(ctx.VoidType(), nil, false) fn := AddFunction(mod, "foo", ftyp) kind := AttributeKindID(name) @@ -104,11 +105,10 @@ func TestAttributes(t *testing.T) { } func TestDebugLoc(t *testing.T) { - mod := NewModule("") + ctx := NewContext() + mod := ctx.NewModule("") defer mod.Dispose() - ctx := mod.Context() - b := ctx.NewBuilder() defer b.Dispose()