The package rpms/tinygo.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/tinygo.git/commit/?id=6da6ac5b43f....
Change:
+ExcludeArch: %{ix86}
Thanks.
Full change:
============
commit b0024804f5404a811e4454beaa596a07e8b478db
Author: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Mon Oct 24 05:50:05 2022 -0400
Backport patches for LLVM 15 support
diff --git a/.gitignore b/.gitignore
index 0f45ff4..4ddee71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
/cmsis_svd-*.tar.gz
/cmsis_svd-*-clean.tar.xz
/compiler-rt-*.src.tar.xz
+/compiler-rt-*.src.tar.xz.sig
/nrfx-*.tar.gz
/picolibc-*.tar.gz
/wasi-libc-*.tar.gz
@@ -32,9 +33,6 @@
/musl-1.2.0.tar.gz
/musl-1.2.0.tar.gz.asc
/tinygo-0.23.0.tar.gz
-/compiler-rt-13.0.0.src.tar.xz.sig
/macos-minimal-sdk-ebb736fda2bec7cea38dcda807518b835a539525.tar.gz
-/compiler-rt-12.0.0.src.tar.xz.sig
-/compiler-rt-14.0.0.src.tar.xz.sig
/tinygo-0.25.0.tar.gz
/tinygo-0.26.0.tar.gz
diff --git a/0001-Skip-WASI-tests.patch b/0001-Skip-WASI-tests.patch
index 6ddce34..1f648df 100644
--- a/0001-Skip-WASI-tests.patch
+++ b/0001-Skip-WASI-tests.patch
@@ -1,7 +1,7 @@
From 6b50974a6d4972b755a35d40d87e5bdf9c97d925 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Tue, 15 Dec 2020 05:06:04 -0500
-Subject: [PATCH 1/6] Skip WASI tests.
+Subject: [PATCH 01/18] Skip WASI tests.
We do not have wasmtime available.
diff --git a/0002-Use-system-mingw64-headers-and-crt.patch
b/0002-Use-system-mingw64-headers-and-crt.patch
index 187daab..821f09a 100644
--- a/0002-Use-system-mingw64-headers-and-crt.patch
+++ b/0002-Use-system-mingw64-headers-and-crt.patch
@@ -1,7 +1,7 @@
From 76c575659d42187b0c4c15d4f5978c4368800da7 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 2 Jan 2022 05:47:18 -0500
-Subject: [PATCH 2/6] Use system mingw64 headers and crt
+Subject: [PATCH 02/18] Use system mingw64 headers and crt
Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
---
diff --git a/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
b/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
index b383fce..87d5c28 100644
--- a/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
+++ b/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
@@ -1,7 +1,7 @@
From 2a2e35e4565e8ea7f7ac2d34cb9da24000bb6474 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Mon, 3 Jan 2022 22:39:31 -0500
-Subject: [PATCH 3/6] Skip some cross Linux tests where qemu is broken
+Subject: [PATCH 03/18] Skip some cross Linux tests where qemu is broken
The upstream issues will hopefully be fixed soon:
diff --git a/0004-Suggest-optional-packages-to-install-if-missing.patch
b/0004-Suggest-optional-packages-to-install-if-missing.patch
index 6f333e2..b7f2c2c 100644
--- a/0004-Suggest-optional-packages-to-install-if-missing.patch
+++ b/0004-Suggest-optional-packages-to-install-if-missing.patch
@@ -1,7 +1,7 @@
From 3f935d679870de924aa65d78c23ecdcb483ab4a3 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 6 Feb 2022 03:49:16 -0500
-Subject: [PATCH 4/6] Suggest optional packages to install if missing
+Subject: [PATCH 04/18] Suggest optional packages to install if missing
Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
---
diff --git a/0005-Skip-TestDirFS-on-32-bit-systems.patch
b/0005-Skip-TestDirFS-on-32-bit-systems.patch
index cdfca0d..9101800 100644
--- a/0005-Skip-TestDirFS-on-32-bit-systems.patch
+++ b/0005-Skip-TestDirFS-on-32-bit-systems.patch
@@ -1,7 +1,7 @@
From 41cbdf1cfe50f24b49beb615f0924ea3255c7e7d Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 8 May 2022 04:18:05 -0400
-Subject: [PATCH 5/6] Skip TestDirFS on 32-bit systems
+Subject: [PATCH 05/18] Skip TestDirFS on 32-bit systems
Because Seek is not fully implemented there.
diff --git a/0006-Skip-broken-tests-on-i686.patch b/0006-Skip-broken-tests-on-i686.patch
index ac4d59f..98e0acf 100644
--- a/0006-Skip-broken-tests-on-i686.patch
+++ b/0006-Skip-broken-tests-on-i686.patch
@@ -1,7 +1,7 @@
From a44f31de099aaf6768af2102919f1a8c221ce6f4 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 8 May 2022 18:39:26 -0400
-Subject: [PATCH 6/6] Skip broken tests on i686
+Subject: [PATCH 06/18] Skip broken tests on i686
* compress/flate runs out of memory
* testing/fstest uses Seek, which is not implemented there
diff --git a/0007-wasm-fix-GC-scanning-of-allocas.patch
b/0007-wasm-fix-GC-scanning-of-allocas.patch
new file mode 100644
index 0000000..02da873
--- /dev/null
+++ b/0007-wasm-fix-GC-scanning-of-allocas.patch
@@ -0,0 +1,265 @@
+From e8f07384a0f5a61351a62931d3fb69bf6c451c1b Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Sun, 16 Oct 2022 00:44:38 +0200
+Subject: [PATCH 07/18] wasm: fix GC scanning of allocas
+
+Scanning of allocas was entirely broken on WebAssembly. The code
+intended to do this was never run. There were also no tests.
+
+Looking into this further, I found that it is actually not really
+necessary to do that: the C stack can be scanned conservatively and in
+fact this was already done for goroutine stacks (because they live on
+the heap and are always referenced). It wasn't done for the system stack
+however.
+
+With these fixes, I believe code should be both faster *and* more
+correct.
+
+I found this in my work to get opaque pointers supported in LLVM 15,
+because the code that was never reached now finally got run and was
+actually quite buggy.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ src/runtime/arch_tinygowasm.go | 3 +++
+ src/runtime/asm_tinygowasm.S | 10 ++++++++++
+ src/runtime/gc_stack_portable.go | 34 +++++++++++++++++++++-----------
+ targets/wasi.json | 3 +++
+ targets/wasm.json | 3 +++
+ transform/gc.go | 30 ++++++++--------------------
+ transform/llvm.go | 28 ++++++++------------------
+ 7 files changed, 57 insertions(+), 54 deletions(-)
+ create mode 100644 src/runtime/asm_tinygowasm.S
+
+diff --git a/src/runtime/arch_tinygowasm.go b/src/runtime/arch_tinygowasm.go
+index 597b2489..f1893d91 100644
+--- a/src/runtime/arch_tinygowasm.go
++++ b/src/runtime/arch_tinygowasm.go
+@@ -58,6 +58,8 @@ var (
+
+ globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
+ globalsEnd = uintptr(unsafe.Pointer(&heapStartSymbol))
++
++ stackTop = uintptr(unsafe.Pointer(&globalsStartSymbol))
+ )
+
+ func align(ptr uintptr) uintptr {
+@@ -67,6 +69,7 @@ func align(ptr uintptr) uintptr {
+ return (ptr + heapAlign - 1) &^ (heapAlign - 1)
+ }
+
++//export tinygo_getCurrentStackPointer
+ func getCurrentStackPointer() uintptr
+
+ // growHeap tries to grow the heap size. It returns true if it succeeds, false
+diff --git a/src/runtime/asm_tinygowasm.S b/src/runtime/asm_tinygowasm.S
+new file mode 100644
+index 00000000..3278a7f6
+--- /dev/null
++++ b/src/runtime/asm_tinygowasm.S
+@@ -0,0 +1,10 @@
++.globaltype __stack_pointer, i32
++
++.global tinygo_getCurrentStackPointer
++.hidden tinygo_getCurrentStackPointer
++.type tinygo_getCurrentStackPointer,@function
++tinygo_getCurrentStackPointer: // func getCurrentStackPointer() uintptr
++ .functype tinygo_getCurrentStackPointer() -> (i32)
++ global.get __stack_pointer
++ return
++ end_function
+diff --git a/src/runtime/gc_stack_portable.go b/src/runtime/gc_stack_portable.go
+index 6ffc35d4..6802de02 100644
+--- a/src/runtime/gc_stack_portable.go
++++ b/src/runtime/gc_stack_portable.go
+@@ -4,6 +4,7 @@
+ package runtime
+
+ import (
++ "internal/task"
+ "unsafe"
+ )
+
+@@ -17,19 +18,28 @@ type stackChainObject struct {
+
+ // markStack marks all root pointers found on the stack.
+ //
+-// This implementation is conservative and relies on the compiler inserting code
+-// to manually push/pop stack objects that are stored in a linked list starting
+-// with stackChainStart. Manually keeping track of stack values is _much_ more
+-// expensive than letting the compiler do it and it inhibits a few important
+-// optimizations, but it has the big advantage of being portable to basically
+-// any ISA, including WebAssembly.
++// - Goroutine stacks are heap allocated and always reachable in some way
++// (for example through internal/task.currentTask) so they will always be
++// scanned.
++// - The system stack (aka startup stack) is not heap allocated, so even
++// though it may be referenced it will not be scanned by default.
++//
++// Therefore, we only need to scan the system stack.
++// It is relatively easy to scan the system stack while we're on it: we can
++// simply read __stack_pointer and __global_base and scan the area inbetween.
++// Unfortunately, it's hard to get the system stack pointer while we're on a
++// goroutine stack. But when we're on a goroutine stack, the system stack is in
++// the scheduler which means there shouldn't be anything on the system stack
++// anyway.
++// ...I hope this assumption holds, otherwise we will need to store the system
++// stack in a global or something.
++//
++// The compiler also inserts code to store all globals in a chain via
++// stackChainStart. Luckily we don't need to scan these, as these globals are
++// stored on the goroutine stack and are therefore already getting scanned.
+ func markStack() {
+- stackObject := stackChainStart
+- for stackObject != nil {
+- start := uintptr(unsafe.Pointer(stackObject)) + unsafe.Sizeof(uintptr(0))*2
+- end := start + stackObject.numSlots*unsafe.Alignof(uintptr(0))
+- markRoots(start, end)
+- stackObject = stackObject.parent
++ if task.OnSystemStack() {
++ markRoots(getCurrentStackPointer(), stackTop)
+ }
+ }
+
+diff --git a/targets/wasi.json b/targets/wasi.json
+index e710b4bb..6cec6be4 100644
+--- a/targets/wasi.json
++++ b/targets/wasi.json
+@@ -18,6 +18,9 @@
+ "--stack-first",
+ "--no-demangle"
+ ],
++ "extra-files": [
++ "src/runtime/asm_tinygowasm.S"
++ ],
+ "emulator": "wasmtime {}",
+ "wasm-abi": "generic"
+ }
+diff --git a/targets/wasm.json b/targets/wasm.json
+index 2bcada5f..26494cc4 100644
+--- a/targets/wasm.json
++++ b/targets/wasm.json
+@@ -19,6 +19,9 @@
+ "--stack-first",
+ "--no-demangle"
+ ],
++ "extra-files": [
++ "src/runtime/asm_tinygowasm.S"
++ ],
+ "emulator": "node {root}/targets/wasm_exec.js {}",
+ "wasm-abi": "js"
+ }
+diff --git a/transform/gc.go b/transform/gc.go
+index eb3520aa..87dc6e88 100644
+--- a/transform/gc.go
++++ b/transform/gc.go
+@@ -139,7 +139,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ }
+
+ // Determine what to do with each call.
+- var allocas, pointers []llvm.Value
++ var pointers []llvm.Value
+ for _, call := range calls {
+ ptr := call.Operand(0)
+ call.EraseFromParentAsInstruction()
+@@ -189,16 +189,15 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ // be optimized if needed.
+ }
+
+- if !ptr.IsAAllocaInst().IsNil() {
+- if typeHasPointers(ptr.Type().ElementType()) {
+- allocas = append(allocas, ptr)
+- }
+- } else {
+- pointers = append(pointers, ptr)
++ if ptr := stripPointerCasts(ptr); !ptr.IsAAllocaInst().IsNil() {
++ // Allocas don't need to be tracked because they are allocated
++ // on the C stack which is scanned separately.
++ continue
+ }
++ pointers = append(pointers, ptr)
+ }
+
+- if len(allocas) == 0 && len(pointers) == 0 {
++ if len(pointers) == 0 {
+ // This function does not need to keep track of stack pointers.
+ continue
+ }
+@@ -208,9 +207,6 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ stackChainStartType, // Pointer to parent frame.
+ uintptrType, // Number of elements in this frame.
+ }
+- for _, alloca := range allocas {
+- fields = append(fields, alloca.Type().ElementType())
+- }
+ for _, ptr := range pointers {
+ fields = append(fields, ptr.Type())
+ }
+@@ -235,16 +231,6 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ stackObjectCast := builder.CreateBitCast(stackObject, stackChainStartType,
"")
+ builder.CreateStore(stackObjectCast, stackChainStart)
+
+- // Replace all independent allocas with GEPs in the stack object.
+- for i, alloca := range allocas {
+- gep := builder.CreateGEP(stackObject, []llvm.Value{
+- llvm.ConstInt(ctx.Int32Type(), 0, false),
+- llvm.ConstInt(ctx.Int32Type(), uint64(2+i), false),
+- }, "")
+- alloca.ReplaceAllUsesWith(gep)
+- alloca.EraseFromParentAsInstruction()
+- }
+-
+ // Do a store to the stack object after each new pointer that is created.
+ pointerStores := make(map[llvm.Value]struct{})
+ for i, ptr := range pointers {
+@@ -260,7 +246,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ // Extract a pointer to the appropriate section of the stack object.
+ gep := builder.CreateGEP(stackObject, []llvm.Value{
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+- llvm.ConstInt(ctx.Int32Type(), uint64(2+len(allocas)+i), false),
++ llvm.ConstInt(ctx.Int32Type(), uint64(2+i), false),
+ }, "")
+
+ // Store the pointer into the stack slot.
+diff --git a/transform/llvm.go b/transform/llvm.go
+index 90b7a7c7..32ee9560 100644
+--- a/transform/llvm.go
++++ b/transform/llvm.go
+@@ -75,26 +75,14 @@ func replaceGlobalIntWithArray(mod llvm.Module, name string, buf
interface{}) ll
+ return global
+ }
+
+-// typeHasPointers returns whether this type is a pointer or contains pointers.
+-// If the type is an aggregate type, it will check whether there is a pointer
+-// inside.
+-func typeHasPointers(t llvm.Type) bool {
+- switch t.TypeKind() {
+- case llvm.PointerTypeKind:
+- return true
+- case llvm.StructTypeKind:
+- for _, subType := range t.StructElementTypes() {
+- if typeHasPointers(subType) {
+- return true
+- }
++// stripPointerCasts strips instruction pointer casts (getelementptr and
++// bitcast) and returns the original value without the casts.
++func stripPointerCasts(value llvm.Value) llvm.Value {
++ if !value.IsAInstruction().IsNil() {
++ switch value.InstructionOpcode() {
++ case llvm.GetElementPtr, llvm.BitCast:
++ return stripPointerCasts(value.Operand(0))
+ }
+- return false
+- case llvm.ArrayTypeKind:
+- if typeHasPointers(t.ElementType()) {
+- return true
+- }
+- return false
+- default:
+- return false
+ }
++ return value
+ }
+--
+2.36.1
+
diff --git a/0008-compiler-return-a-FunctionType-not-a-PointerType-in-.patch
b/0008-compiler-return-a-FunctionType-not-a-PointerType-in-.patch
new file mode 100644
index 0000000..77d6ea3
--- /dev/null
+++ b/0008-compiler-return-a-FunctionType-not-a-PointerType-in-.patch
@@ -0,0 +1,52 @@
+From 9e64a63d49100e550fad97b390bb01489ed6ca44 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Tue, 20 Sep 2022 23:59:22 +0200
+Subject: [PATCH 08/18] compiler: return a FunctionType (not a PointerType) in
+ getRawFuncType
+
+This is necessary for opaque pointer support (in LLVM 15).
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ compiler/func.go | 4 ++--
+ compiler/interface.go | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/compiler/func.go b/compiler/func.go
+index 75656cb7..a8b2874e 100644
+--- a/compiler/func.go
++++ b/compiler/func.go
+@@ -62,7 +62,7 @@ func (b *builder) decodeFuncValue(funcValue llvm.Value, sig
*types.Signature) (f
+ funcPtr = bitcast.Operand(0)
+ return
+ }
+- llvmSig := b.getRawFuncType(sig)
++ llvmSig := llvm.PointerType(b.getRawFuncType(sig), b.funcPtrAddrSpace)
+ funcPtr = b.CreateBitCast(bitcast, llvmSig, "")
+ return
+ }
+@@ -117,7 +117,7 @@ func (c *compilerContext) getRawFuncType(typ *types.Signature)
llvm.Type {
+ paramTypes = append(paramTypes, c.i8ptrType) // context
+
+ // Make a func type out of the signature.
+- return llvm.PointerType(llvm.FunctionType(returnType, paramTypes, false),
c.funcPtrAddrSpace)
++ return llvm.FunctionType(returnType, paramTypes, false)
+ }
+
+ // parseMakeClosure makes a function value (with context) from the given
+diff --git a/compiler/interface.go b/compiler/interface.go
+index c59a9ade..b0ea71e3 100644
+--- a/compiler/interface.go
++++ b/compiler/interface.go
+@@ -465,7 +465,7 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon)
llvm.Value {
+ paramTuple = append(paramTuple, sig.Params().At(i))
+ }
+ paramTuple = append(paramTuple, types.NewVar(token.NoPos, nil, "$typecode",
types.Typ[types.Uintptr]))
+- llvmFnType := c.getRawFuncType(types.NewSignature(sig.Recv(),
types.NewTuple(paramTuple...), sig.Results(), false)).ElementType()
++ llvmFnType := c.getRawFuncType(types.NewSignature(sig.Recv(),
types.NewTuple(paramTuple...), sig.Results(), false))
+ llvmFn = llvm.AddFunction(c.mod, fnName, llvmFnType)
+ c.addStandardDeclaredAttributes(llvmFn)
+ llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("tinygo-invoke",
c.getMethodSignatureName(instr.Method)))
+--
+2.36.1
+
diff --git a/0009-all-add-type-parameter-to-CreateCall.patch
b/0009-all-add-type-parameter-to-CreateCall.patch
new file mode 100644
index 0000000..ca16ea3
--- /dev/null
+++ b/0009-all-add-type-parameter-to-CreateCall.patch
@@ -0,0 +1,993 @@
+From 8138d69793c00829df45501c35975055ad52d151 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Wed, 21 Sep 2022 00:37:01 +0200
+Subject: [PATCH 09/18] all: add type parameter to CreateCall
+
+This uses LLVMBuildCall2 in the background, which is the replacement for
+the deprecated LLVMBuildCall function.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ builder/build.go | 2 +-
+ compiler/alias.go | 2 +-
+ compiler/atomic.go | 4 ++--
+ compiler/calls.go | 14 +++++++-------
+ compiler/compiler.go | 25 ++++++++++++++++---------
+ compiler/defer.go | 16 ++++++++++------
+ compiler/func.go | 8 +++++---
+ compiler/goroutine.go | 33 ++++++++++++++++++---------------
+ compiler/inlineasm.go | 16 ++++++++--------
+ compiler/interface.go | 17 ++++++++---------
+ compiler/interrupt.go | 4 ++--
+ compiler/intrinsics.go | 6 +++---
+ compiler/llvm.go | 2 +-
+ compiler/llvmutil/llvm.go | 24 ++++++++++++++----------
+ compiler/llvmutil/wordpack.go | 4 ++--
+ compiler/symbol.go | 6 +++---
+ compiler/syscall.go | 14 +++++++-------
+ go.mod | 2 +-
+ go.sum | 4 ++--
+ interp/interp.go | 2 +-
+ interp/interpreter.go | 2 +-
+ transform/interface-lowering.go | 7 ++++---
+ transform/interrupt.go | 2 +-
+ transform/panic.go | 2 +-
+ transform/rtcalls.go | 2 +-
+ transform/wasm-abi.go | 6 +++---
+ 26 files changed, 123 insertions(+), 103 deletions(-)
+
+diff --git a/builder/build.go b/builder/build.go
+index 2008c897..28385044 100644
+--- a/builder/build.go
++++ b/builder/build.go
+@@ -523,7 +523,7 @@ func Build(pkgName, outpath string, config *compileopts.Config,
action func(Buil
+ if pkgInit.IsNil() {
+ panic("init not found for " + pkg.Pkg.Path())
+ }
+- irbuilder.CreateCall(pkgInit, []llvm.Value{llvm.Undef(i8ptrType)}, "")
++ irbuilder.CreateCall(pkgInit.GlobalValueType(), pkgInit,
[]llvm.Value{llvm.Undef(i8ptrType)}, "")
+ }
+ irbuilder.CreateRetVoid()
+
+diff --git a/compiler/alias.go b/compiler/alias.go
+index 9e88e3c6..b16cbce8 100644
+--- a/compiler/alias.go
++++ b/compiler/alias.go
+@@ -52,7 +52,7 @@ func (b *builder) createAlias(alias llvm.Value) {
+ b.CreateUnreachable()
+ return
+ }
+- result := b.CreateCall(alias, b.llvmFn.Params(), "")
++ result := b.CreateCall(alias.GlobalValueType(), alias, b.llvmFn.Params(),
"")
+ if result.Type().TypeKind() == llvm.VoidTypeKind {
+ b.CreateRetVoid()
+ } else {
+diff --git a/compiler/atomic.go b/compiler/atomic.go
+index f12c6d11..6ba3849c 100644
+--- a/compiler/atomic.go
++++ b/compiler/atomic.go
+@@ -25,7 +25,7 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
+ if fn.IsNil() {
+ fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(),
vType}, false))
+ }
+- oldVal := b.createCall(fn, []llvm.Value{ptr, val}, "")
++ oldVal := b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val},
"")
+ // Return the new value, not the original value returned.
+ return b.CreateAdd(oldVal, val, "")
+ }
+@@ -78,7 +78,7 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
+ if fn.IsNil() {
+ fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(),
vType, b.uintptrType}, false))
+ }
+- b.createCall(fn, []llvm.Value{ptr, val, llvm.ConstInt(b.uintptrType, 5, false)},
"")
++ b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val,
llvm.ConstInt(b.uintptrType, 5, false)}, "")
+ return llvm.Value{}
+ }
+ store := b.CreateStore(val, ptr)
+diff --git a/compiler/calls.go b/compiler/calls.go
+index aeca518a..b38d770f 100644
+--- a/compiler/calls.go
++++ b/compiler/calls.go
+@@ -37,15 +37,15 @@ const (
+ // createRuntimeInvoke instead.
+ func (b *builder) createRuntimeCallCommon(fnName string, args []llvm.Value, name string,
isInvoke bool) llvm.Value {
+ fn := b.program.ImportedPackage("runtime").Members[fnName].(*ssa.Function)
+- llvmFn := b.getFunction(fn)
++ fnType, llvmFn := b.getFunction(fn)
+ if llvmFn.IsNil() {
+ panic("trying to call non-existent function: " + fn.RelString(nil))
+ }
+ args = append(args, llvm.Undef(b.i8ptrType)) // unused context parameter
+ if isInvoke {
+- return b.createInvoke(llvmFn, args, name)
++ return b.createInvoke(fnType, llvmFn, args, name)
+ }
+- return b.createCall(llvmFn, args, name)
++ return b.createCall(fnType, llvmFn, args, name)
+ }
+
+ // createRuntimeCall creates a new call to runtime.<fnName> with the given
+@@ -65,22 +65,22 @@ func (b *builder) createRuntimeInvoke(fnName string, args
[]llvm.Value, name str
+
+ // createCall creates a call to the given function with the arguments possibly
+ // expanded.
+-func (b *builder) createCall(fn llvm.Value, args []llvm.Value, name string) llvm.Value
{
++func (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name
string) llvm.Value {
+ expanded := make([]llvm.Value, 0, len(args))
+ for _, arg := range args {
+ fragments := b.expandFormalParam(arg)
+ expanded = append(expanded, fragments...)
+ }
+- return b.CreateCall(fn, expanded, name)
++ return b.CreateCall(fnType, fn, expanded, name)
+ }
+
+ // createInvoke is like createCall but continues execution at the landing pad if
+ // the call resulted in a panic.
+-func (b *builder) createInvoke(fn llvm.Value, args []llvm.Value, name string) llvm.Value
{
++func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name
string) llvm.Value {
+ if b.hasDeferFrame() {
+ b.createInvokeCheckpoint()
+ }
+- return b.createCall(fn, args, name)
++ return b.createCall(fnType, fn, args, name)
+ }
+
+ // Expand an argument type to a list that can be used in a function call
+diff --git a/compiler/compiler.go b/compiler/compiler.go
+index bbaf6432..b64fddcc 100644
+--- a/compiler/compiler.go
++++ b/compiler/compiler.go
+@@ -131,6 +131,7 @@ type builder struct {
+ *compilerContext
+ llvm.Builder
+ fn *ssa.Function
++ llvmFnType llvm.Type
+ llvmFn llvm.Value
+ info functionInfo
+ locals map[ssa.Value]llvm.Value // local variables
+@@ -155,11 +156,13 @@ type builder struct {
+ }
+
+ func newBuilder(c *compilerContext, irbuilder llvm.Builder, f *ssa.Function) *builder {
++ fnType, fn := c.getFunction(f)
+ return &builder{
+ compilerContext: c,
+ Builder: irbuilder,
+ fn: f,
+- llvmFn: c.getFunction(f),
++ llvmFnType: fnType,
++ llvmFn: fn,
+ info: c.getFunctionInfo(f),
+ locals: make(map[ssa.Value]llvm.Value),
+ dilocals: make(map[*types.Var]llvm.Metadata),
+@@ -711,7 +714,8 @@ func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata
{
+ // DISubprogram metadata node.
+ func (c *compilerContext) attachDebugInfo(f *ssa.Function) llvm.Metadata {
+ pos := c.program.Fset.Position(f.Syntax().Pos())
+- return c.attachDebugInfoRaw(f, c.getFunction(f), "", pos.Filename, pos.Line)
++ _, fn := c.getFunction(f)
++ return c.attachDebugInfoRaw(f, fn, "", pos.Filename, pos.Line)
+ }
+
+ // attachDebugInfo adds debug info to a function declaration. It returns the
+@@ -1654,6 +1658,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon)
(llvm.Value, error)
+
+ // Try to call the function directly for trivially static calls.
+ var callee, context llvm.Value
++ var calleeType llvm.Type
+ exported := false
+ if fn := instr.StaticCallee(); fn != nil {
+ // Direct function call, either to a named or anonymous (directly
+@@ -1684,7 +1689,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon)
(llvm.Value, error)
+ return b.createInterruptGlobal(instr)
+ }
+
+- callee = b.getFunction(fn)
++ calleeType, callee = b.getFunction(fn)
+ info := b.getFunctionInfo(fn)
+ if callee.IsNil() {
+ return llvm.Value{}, b.makeError(instr.Pos(), "undefined function:
"+info.linkName)
+@@ -1698,8 +1703,8 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon)
(llvm.Value, error)
+ // Eventually we might be able to eliminate this special case
+ // entirely. For details, see:
+ //
https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-i...
+- fnType := llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false)
+- callee = llvm.ConstBitCast(callee, llvm.PointerType(fnType, b.funcPtrAddrSpace))
++ calleeType = llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil,
false)
++ callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType,
b.funcPtrAddrSpace))
+ }
+ case *ssa.MakeClosure:
+ // A call on a func value, but the callee is trivial to find. For
+@@ -1726,13 +1731,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon)
(llvm.Value, error)
+ params = append([]llvm.Value{value}, params...)
+ params = append(params, typecode)
+ callee = b.getInvokeFunction(instr)
++ calleeType = callee.GlobalValueType()
+ context = llvm.Undef(b.i8ptrType)
+ } else {
+ // Function pointer.
+ value := b.getValue(instr.Value)
+ // This is a func value, which cannot be called directly. We have to
+ // extract the function pointer and context first from the func value.
+- callee, context = b.decodeFuncValue(value,
instr.Value.Type().Underlying().(*types.Signature))
++ calleeType, callee, context = b.decodeFuncValue(value,
instr.Value.Type().Underlying().(*types.Signature))
+ b.createNilCheck(instr.Value, callee, "fpcall")
+ }
+
+@@ -1742,7 +1748,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon)
(llvm.Value, error)
+ params = append(params, context)
+ }
+
+- return b.createInvoke(callee, params, ""), nil
++ return b.createInvoke(calleeType, callee, params, ""), nil
+ }
+
+ // getValue returns the LLVM value of a constant, function value, global, or
+@@ -1756,7 +1762,8 @@ func (b *builder) getValue(expr ssa.Value) llvm.Value {
+ b.addError(expr.Pos(), "cannot use an exported function as value:
"+expr.String())
+ return llvm.Undef(b.getLLVMType(expr.Type()))
+ }
+- return b.createFuncValue(b.getFunction(expr), llvm.Undef(b.i8ptrType),
expr.Signature)
++ _, fn := b.getFunction(expr)
++ return b.createFuncValue(fn, llvm.Undef(b.i8ptrType), expr.Signature)
+ case *ssa.Global:
+ value := b.getGlobal(expr)
+ if value.IsNil() {
+@@ -3080,7 +3087,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
+ // Instead of a load from the global, create a bitcast of the
+ // function pointer itself.
+ name := strings.TrimSuffix(unop.X.(*ssa.Global).Name(), "$funcaddr")
+- fn := b.getFunction(b.fn.Pkg.Members[name].(*ssa.Function))
++ _, fn := b.getFunction(b.fn.Pkg.Members[name].(*ssa.Function))
+ if fn.IsNil() {
+ return llvm.Value{}, b.makeError(unop.Pos(), "cgo function not found:
"+name)
+ }
+diff --git a/compiler/defer.go b/compiler/defer.go
+index 75c1be3d..e82370fa 100644
+--- a/compiler/defer.go
++++ b/compiler/defer.go
+@@ -201,7 +201,7 @@ li a0, 0
+ }
+ asmType := llvm.FunctionType(resultType, []llvm.Type{b.deferFrame.Type()}, false)
+ asm := llvm.InlineAsm(asmType, asmString, constraints, false, false, 0, false)
+- result := b.CreateCall(asm, []llvm.Value{b.deferFrame}, "setjmp")
++ result := b.CreateCall(asmType, asm, []llvm.Value{b.deferFrame}, "setjmp")
+ result.AddCallSiteAttribute(-1,
b.ctx.CreateEnumAttribute(llvm.AttributeKindID("returns_twice"), 0))
+ isZero := b.CreateICmp(llvm.IntEQ, result, llvm.ConstInt(resultType, 0, false),
"setjmp.result")
+ continueBB := b.insertBasicBlock("")
+@@ -492,6 +492,7 @@ func (b *builder) createRunDefers() {
+ }
+
+ var fnPtr llvm.Value
++ var fnType llvm.Type
+
+ if !callback.IsInvoke() {
+ // Isolate the func value.
+@@ -499,8 +500,8 @@ func (b *builder) createRunDefers() {
+ forwardParams = forwardParams[1:]
+
+ //Get function pointer and context
+- fp, context := b.decodeFuncValue(funcValue, callback.Signature())
+- fnPtr = fp
++ var context llvm.Value
++ fnType, fnPtr, context = b.decodeFuncValue(funcValue, callback.Signature())
+
+ //Pass context
+ forwardParams = append(forwardParams, context)
+@@ -509,6 +510,7 @@ func (b *builder) createRunDefers() {
+ // parameters.
+ forwardParams = append(forwardParams[1:], forwardParams[0])
+ fnPtr = b.getInvokeFunction(callback)
++ fnType = fnPtr.GlobalValueType()
+
+ // Add the context parameter. An interface call cannot also be a
+ // closure but we have to supply the parameter anyway for platforms
+@@ -516,7 +518,7 @@ func (b *builder) createRunDefers() {
+ forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
+ }
+
+- b.createCall(fnPtr, forwardParams, "")
++ b.createCall(fnType, fnPtr, forwardParams, "")
+
+ case *ssa.Function:
+ // Direct call.
+@@ -547,7 +549,8 @@ func (b *builder) createRunDefers() {
+ }
+
+ // Call real function.
+- b.createInvoke(b.getFunction(callback), forwardParams, "")
++ fnType, fn := b.getFunction(callback)
++ b.createInvoke(fnType, fn, forwardParams, "")
+
+ case *ssa.MakeClosure:
+ // Get the real defer struct type and cast to it.
+@@ -571,7 +574,8 @@ func (b *builder) createRunDefers() {
+ }
+
+ // Call deferred function.
+- b.createCall(b.getFunction(fn), forwardParams, "")
++ fnType, llvmFn := b.getFunction(fn)
++ b.createCall(fnType, llvmFn, forwardParams, "")
+ case *ssa.Builtin:
+ db := b.deferBuiltinFuncs[callback]
+
+diff --git a/compiler/func.go b/compiler/func.go
+index a8b2874e..c6a8802d 100644
+--- a/compiler/func.go
++++ b/compiler/func.go
+@@ -55,14 +55,15 @@ func (b *builder) extractFuncContext(funcValue llvm.Value) llvm.Value
{
+
+ // decodeFuncValue extracts the context and the function pointer from this func
+ // value. This may be an expensive operation.
+-func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcPtr,
context llvm.Value) {
++func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcType
llvm.Type, funcPtr, context llvm.Value) {
+ context = b.CreateExtractValue(funcValue, 0, "")
+ bitcast := b.CreateExtractValue(funcValue, 1, "")
+ if !bitcast.IsAConstantExpr().IsNil() && bitcast.Opcode() == llvm.BitCast {
+ funcPtr = bitcast.Operand(0)
+ return
+ }
+- llvmSig := llvm.PointerType(b.getRawFuncType(sig), b.funcPtrAddrSpace)
++ funcType = b.getRawFuncType(sig)
++ llvmSig := llvm.PointerType(funcType, b.funcPtrAddrSpace)
+ funcPtr = b.CreateBitCast(bitcast, llvmSig, "")
+ return
+ }
+@@ -141,5 +142,6 @@ func (b *builder) parseMakeClosure(expr *ssa.MakeClosure)
(llvm.Value, error) {
+ context := b.emitPointerPack(boundVars)
+
+ // Create the closure.
+- return b.createFuncValue(b.getFunction(f), context, f.Signature), nil
++ _, fn := b.getFunction(f)
++ return b.createFuncValue(fn, context, f.Signature), nil
+ }
+diff --git a/compiler/goroutine.go b/compiler/goroutine.go
+index 8d76c89f..ba8ec0f4 100644
+--- a/compiler/goroutine.go
++++ b/compiler/goroutine.go
+@@ -22,6 +22,7 @@ func (b *builder) createGo(instr *ssa.Go) {
+
+ var prefix string
+ var funcPtr llvm.Value
++ var funcPtrType llvm.Type
+ hasContext := false
+ if callee := instr.Call.StaticCallee(); callee != nil {
+ // Static callee is known. This makes it easier to start a new
+@@ -42,7 +43,7 @@ func (b *builder) createGo(instr *ssa.Go) {
+ params = append(params, context) // context parameter
+ hasContext = true
+ }
+- funcPtr = b.getFunction(callee)
++ funcPtrType, funcPtr = b.getFunction(callee)
+ } else if builtin, ok := instr.Call.Value.(*ssa.Builtin); ok {
+ // We cheat. None of the builtins do any long or blocking operation, so
+ // we might as well run these builtins right away without the program
+@@ -80,6 +81,7 @@ func (b *builder) createGo(instr *ssa.Go) {
+ itfTypeCode := b.CreateExtractValue(itf, 0, "")
+ itfValue := b.CreateExtractValue(itf, 1, "")
+ funcPtr = b.getInvokeFunction(&instr.Call)
++ funcPtrType = funcPtr.GlobalValueType()
+ params = append([]llvm.Value{itfValue}, params...) // start with receiver
+ params = append(params, itfTypeCode) // end with typecode
+ } else {
+@@ -89,7 +91,7 @@ func (b *builder) createGo(instr *ssa.Go) {
+ // * The function context, for closures.
+ // * The function pointer (for tasks).
+ var context llvm.Value
+- funcPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value),
instr.Call.Value.Type().Underlying().(*types.Signature))
++ funcPtrType, funcPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value),
instr.Call.Value.Type().Underlying().(*types.Signature))
+ params = append(params, context, funcPtr)
+ hasContext = true
+ prefix = b.fn.RelString(nil)
+@@ -97,14 +99,14 @@ func (b *builder) createGo(instr *ssa.Go) {
+
+ paramBundle := b.emitPointerPack(params)
+ var stackSize llvm.Value
+- callee := b.createGoroutineStartWrapper(funcPtr, prefix, hasContext, instr.Pos())
++ callee := b.createGoroutineStartWrapper(funcPtrType, funcPtr, prefix, hasContext,
instr.Pos())
+ if b.AutomaticStackSize {
+ // The stack size is not known until after linking. Call a dummy
+ // function that will be replaced with a load from a special ELF
+ // section that contains the stack size (and is modified after
+ // linking).
+- stackSizeFn :=
b.getFunction(b.program.ImportedPackage("internal/task").Members["getGoroutineStackSize"].(*ssa.Function))
+- stackSize = b.createCall(stackSizeFn, []llvm.Value{callee, llvm.Undef(b.i8ptrType)},
"stacksize")
++ stackSizeFnType, stackSizeFn :=
b.getFunction(b.program.ImportedPackage("internal/task").Members["getGoroutineStackSize"].(*ssa.Function))
++ stackSize = b.createCall(stackSizeFnType, stackSizeFn, []llvm.Value{callee,
llvm.Undef(b.i8ptrType)}, "stacksize")
+ } else {
+ // The stack size is fixed at compile time. By emitting it here as a
+ // constant, it can be optimized.
+@@ -113,8 +115,8 @@ func (b *builder) createGo(instr *ssa.Go) {
+ }
+ stackSize = llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false)
+ }
+- start :=
b.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function))
+- b.createCall(start, []llvm.Value{callee, paramBundle, stackSize,
llvm.Undef(b.i8ptrType)}, "")
++ fnType, start :=
b.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function))
++ b.createCall(fnType, start, []llvm.Value{callee, paramBundle, stackSize,
llvm.Undef(b.i8ptrType)}, "")
+ }
+
+ // createGoroutineStartWrapper creates a wrapper for the task-based
+@@ -140,15 +142,16 @@ func (b *builder) createGo(instr *ssa.Go) {
+ // to last parameter of the function) is used for this wrapper. If hasContext is
+ // false, the parameter bundle is assumed to have no context parameter and undef
+ // is passed instead.
+-func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix string,
hasContext bool, pos token.Pos) llvm.Value {
++func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value,
prefix string, hasContext bool, pos token.Pos) llvm.Value {
+ var wrapper llvm.Value
+
+ builder := c.ctx.NewBuilder()
+ defer builder.Dispose()
+
+ var deadlock llvm.Value
++ var deadlockType llvm.Type
+ if c.Scheduler == "asyncify" {
+- deadlock =
c.getFunction(c.program.ImportedPackage("runtime").Members["deadlock"].(*ssa.Function))
++ deadlockType, deadlock =
c.getFunction(c.program.ImportedPackage("runtime").Members["deadlock"].(*ssa.Function))
+ }
+
+ if !fn.IsAFunction().IsNil() {
+@@ -192,7 +195,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value,
prefix stri
+ }
+
+ // Create the list of params for the call.
+- paramTypes := fn.Type().ElementType().ParamTypes()
++ paramTypes := fnType.ParamTypes()
+ if !hasContext {
+ paramTypes = paramTypes[:len(paramTypes)-1] // strip context parameter
+ }
+@@ -202,10 +205,10 @@ func (c *compilerContext) createGoroutineStartWrapper(fn
llvm.Value, prefix stri
+ }
+
+ // Create the call.
+- builder.CreateCall(fn, params, "")
++ builder.CreateCall(fnType, fn, params, "")
+
+ if c.Scheduler == "asyncify" {
+- builder.CreateCall(deadlock, []llvm.Value{
++ builder.CreateCall(deadlockType, deadlock, []llvm.Value{
+ llvm.Undef(c.i8ptrType),
+ }, "")
+ }
+@@ -261,7 +264,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value,
prefix stri
+ }
+
+ // Get the list of parameters, with the extra parameters at the end.
+- paramTypes := fn.Type().ElementType().ParamTypes()
++ paramTypes := fnType.ParamTypes()
+ paramTypes = append(paramTypes, fn.Type()) // the last element is the function
pointer
+ params := llvmutil.EmitPointerUnpack(builder, c.mod, wrapper.Param(0), paramTypes)
+
+@@ -270,10 +273,10 @@ func (c *compilerContext) createGoroutineStartWrapper(fn
llvm.Value, prefix stri
+ params = params[:len(params)-1]
+
+ // Create the call.
+- builder.CreateCall(fnPtr, params, "")
++ builder.CreateCall(fnType, fnPtr, params, "")
+
+ if c.Scheduler == "asyncify" {
+- builder.CreateCall(deadlock, []llvm.Value{
++ builder.CreateCall(deadlockType, deadlock, []llvm.Value{
+ llvm.Undef(c.i8ptrType),
+ }, "")
+ }
+diff --git a/compiler/inlineasm.go b/compiler/inlineasm.go
+index 27b0492b..2afb0a16 100644
+--- a/compiler/inlineasm.go
++++ b/compiler/inlineasm.go
+@@ -25,7 +25,7 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error)
{
+ fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{}, false)
+ asm := constant.StringVal(args[0].(*ssa.Const).Value)
+ target := llvm.InlineAsm(fnType, asm, "", true, false, 0, false)
+- return b.CreateCall(target, nil, ""), nil
++ return b.CreateCall(fnType, target, nil, ""), nil
+ }
+
+ // This is a compiler builtin, which allows assembly to be called in a flexible
+@@ -120,7 +120,7 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon)
(llvm.Value, error)
+ }
+ fnType := llvm.FunctionType(outputType, argTypes, false)
+ target := llvm.InlineAsm(fnType, asmString, strings.Join(constraints, ","),
true, false, 0, false)
+- result := b.CreateCall(target, args, "")
++ result := b.CreateCall(fnType, target, args, "")
+ if hasOutput {
+ return result, nil
+ } else {
+@@ -163,7 +163,7 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
+ constraints += ",~{r1},~{r2},~{r3}"
+ fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
+ target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
+- return b.CreateCall(target, llvmArgs, ""), nil
++ return b.CreateCall(fnType, target, llvmArgs, ""), nil
+ }
+
+ // This is a compiler builtin which emits an inline SVCall instruction. It can
+@@ -201,7 +201,7 @@ func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error)
{
+ constraints += ",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}"
+ fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
+ target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)
+- return b.CreateCall(target, llvmArgs, ""), nil
++ return b.CreateCall(fnType, target, llvmArgs, ""), nil
+ }
+
+ // This is a compiler builtin which emits CSR instructions. It can be one of:
+@@ -226,24 +226,24 @@ func (b *builder) emitCSROperation(call *ssa.CallCommon)
(llvm.Value, error) {
+ fnType := llvm.FunctionType(b.uintptrType, nil, false)
+ asm := fmt.Sprintf("csrr $0, %d", csr)
+ target := llvm.InlineAsm(fnType, asm, "=r", true, false, 0, false)
+- return b.CreateCall(target, nil, ""), nil
++ return b.CreateCall(fnType, target, nil, ""), nil
+ case "Set":
+ fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.uintptrType}, false)
+ asm := fmt.Sprintf("csrw %d, $0", csr)
+ target := llvm.InlineAsm(fnType, asm, "r", true, false, 0, false)
+- return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""),
nil
++ return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])},
""), nil
+ case "SetBits":
+ // Note: it may be possible to optimize this to csrrsi in many cases.
+ fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)
+ asm := fmt.Sprintf("csrrs $0, %d, $1", csr)
+ target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0, false)
+- return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""),
nil
++ return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])},
""), nil
+ case "ClearBits":
+ // Note: it may be possible to optimize this to csrrci in many cases.
+ fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)
+ asm := fmt.Sprintf("csrrc $0, %d, $1", csr)
+ target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0, false)
+- return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""),
nil
++ return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])},
""), nil
+ default:
+ return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation:
"+name)
+ }
+diff --git a/compiler/interface.go b/compiler/interface.go
+index b0ea71e3..72f8952d 100644
+--- a/compiler/interface.go
++++ b/compiler/interface.go
+@@ -254,12 +254,12 @@ func (c *compilerContext) getTypeMethodSet(typ types.Type)
llvm.Value {
+ method := ms.At(i)
+ signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
+ fn := c.program.MethodValue(method)
+- llvmFn := c.getFunction(fn)
++ llvmFnType, llvmFn := c.getFunction(fn)
+ if llvmFn.IsNil() {
+ // compiler error, so panic
+ panic("cannot find function: " + c.getFunctionInfo(fn).linkName)
+ }
+- wrapper := c.getInterfaceInvokeWrapper(fn, llvmFn)
++ wrapper := c.getInterfaceInvokeWrapper(fn, llvmFnType, llvmFn)
+ methodInfo := llvm.ConstNamedStruct(interfaceMethodInfoType, []llvm.Value{
+ signatureGlobal,
+ llvm.ConstPtrToInt(wrapper, c.uintptrType),
+@@ -361,7 +361,7 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value
{
+ // implements each method of the interface. See:
+ //
https://research.swtch.com/interfaces
+ fn := b.getInterfaceImplementsFunc(expr.AssertedType)
+- commaOk = b.CreateCall(fn, []llvm.Value{actualTypeNum}, "")
++ commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum},
"")
+
+ } else {
+ globalName := "reflect/types.typeid:" + getTypeCodeName(expr.AssertedType)
+@@ -480,7 +480,7 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon)
llvm.Value {
+ // value, dereferences or unpacks it if necessary, and calls the real method.
+ // If the method to wrap has a pointer receiver, no wrapping is necessary and
+ // the function is returned directly.
+-func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llvm.Value)
llvm.Value {
++func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFnType
llvm.Type, llvmFn llvm.Value) llvm.Value {
+ wrapperName := llvmFn.Name() + "$invoke"
+ wrapper := c.mod.NamedFunction(wrapperName)
+ if !wrapper.IsNil() {
+@@ -505,9 +505,8 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function,
llvmFn llv
+ }
+
+ // create wrapper function
+- fnType := llvmFn.Type().ElementType()
+- paramTypes := append([]llvm.Type{c.i8ptrType},
fnType.ParamTypes()[len(expandedReceiverType):]...)
+- wrapFnType := llvm.FunctionType(fnType.ReturnType(), paramTypes, false)
++ paramTypes := append([]llvm.Type{c.i8ptrType},
llvmFnType.ParamTypes()[len(expandedReceiverType):]...)
++ wrapFnType := llvm.FunctionType(llvmFnType.ReturnType(), paramTypes, false)
+ wrapper = llvm.AddFunction(c.mod, wrapperName, wrapFnType)
+ c.addStandardAttributes(wrapper)
+
+@@ -535,10 +534,10 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn
*ssa.Function, llvmFn llv
+ receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0]
+ params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...)
+ if llvmFn.Type().ElementType().ReturnType().TypeKind() == llvm.VoidTypeKind {
+- b.CreateCall(llvmFn, params, "")
++ b.CreateCall(llvmFnType, llvmFn, params, "")
+ b.CreateRetVoid()
+ } else {
+- ret := b.CreateCall(llvmFn, params, "ret")
++ ret := b.CreateCall(llvmFnType, llvmFn, params, "ret")
+ b.CreateRet(ret)
+ }
+
+diff --git a/compiler/interrupt.go b/compiler/interrupt.go
+index bcd407cd..45c7d074 100644
+--- a/compiler/interrupt.go
++++ b/compiler/interrupt.go
+@@ -36,7 +36,7 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon)
(llvm.Value, erro
+ // Fall back to a generic error.
+ return llvm.Value{}, b.makeError(instr.Pos(), "interrupt function must be
constant")
+ }
+- funcRawPtr, funcContext := b.decodeFuncValue(funcValue, nil)
++ _, funcRawPtr, funcContext := b.decodeFuncValue(funcValue, nil)
+ funcPtr := llvm.ConstPtrToInt(funcRawPtr, b.uintptrType)
+
+ // Create a new global of type runtime/interrupt.handle. Globals of this
+@@ -85,7 +85,7 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon)
(llvm.Value, erro
+ useFnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{interrupt.Type()},
false)
+ useFn = llvm.AddFunction(b.mod, "runtime/interrupt.use", useFnType)
+ }
+- b.CreateCall(useFn, []llvm.Value{interrupt}, "")
++ b.CreateCall(useFn.GlobalValueType(), useFn, []llvm.Value{interrupt}, "")
+ }
+
+ return interrupt, nil
+diff --git a/compiler/intrinsics.go b/compiler/intrinsics.go
+index 0203d441..9fedfbd6 100644
+--- a/compiler/intrinsics.go
++++ b/compiler/intrinsics.go
+@@ -55,7 +55,7 @@ func (b *builder) createMemoryCopyImpl() {
+ params = append(params, b.getValue(param))
+ }
+ params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))
+- b.CreateCall(llvmFn, params, "")
++ b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
+ b.CreateRetVoid()
+ }
+
+@@ -76,7 +76,7 @@ func (b *builder) createMemoryZeroImpl() {
+ b.getValue(b.fn.Params[1]),
+ llvm.ConstInt(b.ctx.Int1Type(), 0, false),
+ }
+- b.CreateCall(llvmFn, params, "")
++ b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
+ b.CreateRetVoid()
+ }
+
+@@ -119,6 +119,6 @@ func (b *builder) defineMathOp() {
+ for i, param := range b.fn.Params {
+ args[i] = b.getValue(param)
+ }
+- result := b.CreateCall(llvmFn, args, "")
++ result := b.CreateCall(llvmFn.GlobalValueType(), llvmFn, args, "")
+ b.CreateRet(result)
+ }
+diff --git a/compiler/llvm.go b/compiler/llvm.go
+index 0d2ba9da..9540bcc6 100644
+--- a/compiler/llvm.go
++++ b/compiler/llvm.go
+@@ -312,5 +312,5 @@ func (b *builder) readStackPointer() llvm.Value {
+ fnType := llvm.FunctionType(b.i8ptrType, nil, false)
+ stacksave = llvm.AddFunction(b.mod, "llvm.stacksave", fnType)
+ }
+- return b.CreateCall(stacksave, nil, "")
++ return b.CreateCall(stacksave.GlobalValueType(), stacksave, nil, "")
+ }
+diff --git a/compiler/llvmutil/llvm.go b/compiler/llvmutil/llvm.go
+index 74404a3e..e73b68da 100644
+--- a/compiler/llvmutil/llvm.go
++++ b/compiler/llvmutil/llvm.go
+@@ -39,7 +39,8 @@ func CreateTemporaryAlloca(builder llvm.Builder, mod llvm.Module, t
llvm.Type, n
+ alloca = CreateEntryBlockAlloca(builder, t, name)
+ bitcast = builder.CreateBitCast(alloca, i8ptrType, name+".bitcast")
+ size = llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false)
+- builder.CreateCall(getLifetimeStartFunc(mod), []llvm.Value{size, bitcast},
"")
++ fnType, fn := getLifetimeStartFunc(mod)
++ builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "")
+ return
+ }
+
+@@ -54,13 +55,15 @@ func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t
llvm.Type,
+ builder.SetInsertPointBefore(inst)
+ bitcast := builder.CreateBitCast(alloca, i8ptrType, name+".bitcast")
+ size := llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false)
+- builder.CreateCall(getLifetimeStartFunc(mod), []llvm.Value{size, bitcast},
"")
++ fnType, fn := getLifetimeStartFunc(mod)
++ builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "")
+ if next := llvm.NextInstruction(inst); !next.IsNil() {
+ builder.SetInsertPointBefore(next)
+ } else {
+ builder.SetInsertPointAtEnd(inst.InstructionParent())
+ }
+- builder.CreateCall(getLifetimeEndFunc(mod), []llvm.Value{size, bitcast}, "")
++ fnType, fn = getLifetimeEndFunc(mod)
++ builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "")
+ return alloca
+ }
+
+@@ -68,33 +71,34 @@ func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t
llvm.Type,
+ // llvm.lifetime.end intrinsic. It is commonly used together with
+ // createTemporaryAlloca.
+ func EmitLifetimeEnd(builder llvm.Builder, mod llvm.Module, ptr, size llvm.Value) {
+- builder.CreateCall(getLifetimeEndFunc(mod), []llvm.Value{size, ptr}, "")
++ fnType, fn := getLifetimeEndFunc(mod)
++ builder.CreateCall(fnType, fn, []llvm.Value{size, ptr}, "")
+ }
+
+ // getLifetimeStartFunc returns the llvm.lifetime.start intrinsic and creates it
+ // first if it doesn't exist yet.
+-func getLifetimeStartFunc(mod llvm.Module) llvm.Value {
++func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
+ fn := mod.NamedFunction("llvm.lifetime.start.p0i8")
+ ctx := mod.Context()
+ i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
++ fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType},
false)
+ if fn.IsNil() {
+- fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType},
false)
+ fn = llvm.AddFunction(mod, "llvm.lifetime.start.p0i8", fnType)
+ }
+- return fn
++ return fnType, fn
+ }
+
+ // getLifetimeEndFunc returns the llvm.lifetime.end intrinsic and creates it
+ // first if it doesn't exist yet.
+-func getLifetimeEndFunc(mod llvm.Module) llvm.Value {
++func getLifetimeEndFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
+ fn := mod.NamedFunction("llvm.lifetime.end.p0i8")
+ ctx := mod.Context()
+ i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
++ fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType},
false)
+ if fn.IsNil() {
+- fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType},
false)
+ fn = llvm.AddFunction(mod, "llvm.lifetime.end.p0i8", fnType)
+ }
+- return fn
++ return fnType, fn
+ }
+
+ // SplitBasicBlock splits a LLVM basic block into two parts. All instructions
+diff --git a/compiler/llvmutil/wordpack.go b/compiler/llvmutil/wordpack.go
+index 41d4c581..73b1e27e 100644
+--- a/compiler/llvmutil/wordpack.go
++++ b/compiler/llvmutil/wordpack.go
+@@ -95,14 +95,14 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix
string, needs
+ // Packed data is bigger than a pointer, so allocate it on the heap.
+ sizeValue := llvm.ConstInt(uintptrType, size, false)
+ alloc := mod.NamedFunction("runtime.alloc")
+- packedHeapAlloc := builder.CreateCall(alloc, []llvm.Value{
++ packedHeapAlloc := builder.CreateCall(alloc.GlobalValueType(), alloc, []llvm.Value{
+ sizeValue,
+ llvm.ConstNull(i8ptrType),
+ llvm.Undef(i8ptrType), // unused context parameter
+ }, "")
+ if needsStackObjects {
+ trackPointer := mod.NamedFunction("runtime.trackPointer")
+- builder.CreateCall(trackPointer, []llvm.Value{
++ builder.CreateCall(trackPointer.GlobalValueType(), trackPointer, []llvm.Value{
+ packedHeapAlloc,
+ llvm.Undef(i8ptrType), // unused context parameter
+ }, "")
+diff --git a/compiler/symbol.go b/compiler/symbol.go
+index c4ce6f21..83fe050b 100644
+--- a/compiler/symbol.go
++++ b/compiler/symbol.go
+@@ -53,11 +53,11 @@ const (
+
+ // getFunction returns the LLVM function for the given *ssa.Function, creating
+ // it if needed. It can later be filled with compilerContext.createFunction().
+-func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
++func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) {
+ info := c.getFunctionInfo(fn)
+ llvmFn := c.mod.NamedFunction(info.linkName)
+ if !llvmFn.IsNil() {
+- return llvmFn
++ return llvmFn.GlobalValueType(), llvmFn
+ }
+
+ var retType llvm.Type
+@@ -202,7 +202,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
+ llvmFn.SetUnnamedAddr(true)
+ }
+
+- return llvmFn
++ return fnType, llvmFn
+ }
+
+ // getFunctionInfo returns information about a function that is not directly
+diff --git a/compiler/syscall.go b/compiler/syscall.go
+index 0c5f1246..66baf826 100644
+--- a/compiler/syscall.go
++++ b/compiler/syscall.go
+@@ -44,7 +44,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value,
error) {
+ constraints += ",~{rcx},~{r11}"
+ fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
+ target := llvm.InlineAsm(fnType, "syscall", constraints, true, false,
llvm.InlineAsmDialectIntel, false)
+- return b.CreateCall(target, args, ""), nil
++ return b.CreateCall(fnType, target, args, ""), nil
+ case b.GOARCH == "386" && b.GOOS == "linux":
+ // Sources:
+ // syscall(2) man page
+@@ -70,7 +70,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value,
error) {
+ }
+ fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
+ target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false,
llvm.InlineAsmDialectIntel, false)
+- return b.CreateCall(target, args, ""), nil
++ return b.CreateCall(fnType, target, args, ""), nil
+ case b.GOARCH == "arm" && b.GOOS == "linux":
+ // Implement the EABI system call convention for Linux.
+ // Source: syscall(2) man page.
+@@ -102,7 +102,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value,
error) {
+ }
+ fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
+ target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0,
false)
+- return b.CreateCall(target, args, ""), nil
++ return b.CreateCall(fnType, target, args, ""), nil
+ case b.GOARCH == "arm64" && b.GOOS == "linux":
+ // Source: syscall(2) man page.
+ args := []llvm.Value{}
+@@ -134,7 +134,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value,
error) {
+ constraints += ",~{x16},~{x17}" // scratch registers
+ fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
+ target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0,
false)
+- return b.CreateCall(target, args, ""), nil
++ return b.CreateCall(fnType, target, args, ""), nil
+ default:
+ return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall:
"+b.GOOS+"/"+b.GOARCH)
+ }
+@@ -205,9 +205,9 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value,
error) {
+ // Note that SetLastError/GetLastError could be replaced with direct
+ // access to the thread control block, which is probably smaller and
+ // faster. The Go runtime does this in assembly.
+- b.CreateCall(setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())},
"")
+- syscallResult := b.CreateCall(fnPtr, params, "")
+- errResult := b.CreateCall(getLastError, nil, "err")
++ b.CreateCall(setLastError.GlobalValueType(), setLastError,
[]llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "")
++ syscallResult := b.CreateCall(llvmType, fnPtr, params, "")
++ errResult := b.CreateCall(getLastError.GlobalValueType(), getLastError, nil,
"err")
+ if b.uintptrType != b.ctx.Int32Type() {
+ errResult = b.CreateZExt(errResult, b.uintptrType, "err.uintptr")
+ }
+diff --git a/go.mod b/go.mod
+index fdf686d4..4af10427 100644
+--- a/go.mod
++++ b/go.mod
+@@ -17,7 +17,7 @@ require (
+
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
+
golang.org/x/tools v0.1.11
+ gopkg.in/yaml.v2 v2.4.0
+-
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7
++
tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636
+ )
+
+ require (
+diff --git a/go.sum b/go.sum
+index 3fc9cac1..401de3be 100644
+--- a/go.sum
++++ b/go.sum
+@@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod
h1:Co6ibVJAznAaIkqp8
+ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+-tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7
h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
+-tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
++tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636
h1:JxtI6P/lyWHAcs/4QJWeWIbh4HntxPFONMVWvx7wf8Y=
++tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+diff --git a/interp/interp.go b/interp/interp.go
+index a1f5f507..856f08b1 100644
+--- a/interp/interp.go
++++ b/interp/interp.go
+@@ -127,7 +127,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
+ // Create a call to the package initializer (which was
+ // previously deleted).
+ i8undef := llvm.Undef(r.i8ptrType)
+- r.builder.CreateCall(fn, []llvm.Value{i8undef}, "")
++ r.builder.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{i8undef}, "")
+ // Make sure that any globals touched by the package
+ // initializer, won't be accessed by later package initializers.
+ err := r.markExternalLoad(fn)
+diff --git a/interp/interpreter.go b/interp/interpreter.go
+index 7cee14bf..4a4553f8 100644
+--- a/interp/interpreter.go
++++ b/interp/interpreter.go
+@@ -977,7 +977,7 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals
[]value, me
+ }
+ }
+ }
+- result = r.builder.CreateCall(llvmFn, args, inst.name)
++ result = r.builder.CreateCall(inst.llvmInst.CalledFunctionType(), llvmFn, args,
inst.name)
+ case llvm.Load:
+ err := mem.markExternalLoad(operands[0])
+ if err != nil {
+diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go
+index 7a01c2ea..f5b29e30 100644
+--- a/transform/interface-lowering.go
++++ b/transform/interface-lowering.go
+@@ -493,12 +493,13 @@ func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn
llvm.Value, itf *inte
+ paramTypes = append(paramTypes, param.Type())
+ }
+ calledFunctionType := function.Type()
+- sig := llvm.PointerType(llvm.FunctionType(returnType, paramTypes, false),
calledFunctionType.PointerAddressSpace())
++ functionType := llvm.FunctionType(returnType, paramTypes, false)
++ sig := llvm.PointerType(functionType, calledFunctionType.PointerAddressSpace())
+ if sig != function.Type() {
+ function = p.builder.CreateBitCast(function, sig, "")
+ }
+
+- retval := p.builder.CreateCall(function, append([]llvm.Value{receiver}, params...),
"")
++ retval := p.builder.CreateCall(functionType, function, append([]llvm.Value{receiver},
params...), "")
+ if retval.Type().TypeKind() == llvm.VoidTypeKind {
+ p.builder.CreateRetVoid()
+ } else {
+@@ -518,7 +519,7 @@ func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn
llvm.Value, itf *inte
+ // importantly, it avoids undefined behavior when accidentally calling a
+ // method on a nil interface.
+ nilPanic := p.mod.NamedFunction("runtime.nilPanic")
+- p.builder.CreateCall(nilPanic, []llvm.Value{
++ p.builder.CreateCall(nilPanic.GlobalValueType(), nilPanic, []llvm.Value{
+ llvm.Undef(llvm.PointerType(p.ctx.Int8Type(), 0)),
+ }, "")
+ p.builder.CreateUnreachable()
+diff --git a/transform/interrupt.go b/transform/interrupt.go
+index 3ffe7048..2c301be0 100644
+--- a/transform/interrupt.go
++++ b/transform/interrupt.go
+@@ -91,7 +91,7 @@ func LowerInterrupts(mod llvm.Module) []error {
+ initializer := handler.Initializer()
+ context := llvm.ConstExtractValue(initializer, []uint32{0})
+ funcPtr := llvm.ConstExtractValue(initializer, []uint32{1}).Operand(0)
+- builder.CreateCall(funcPtr, []llvm.Value{
++ builder.CreateCall(funcPtr.GlobalValueType(), funcPtr, []llvm.Value{
+ num,
+ context,
+ }, "")
+diff --git a/transform/panic.go b/transform/panic.go
+index e8e9a1fe..dee3bae0 100644
+--- a/transform/panic.go
++++ b/transform/panic.go
+@@ -27,7 +27,7 @@ func ReplacePanicsWithTrap(mod llvm.Module) {
+ panic("expected use of a panic function to be a call")
+ }
+ builder.SetInsertPointBefore(use)
+- builder.CreateCall(trap, nil, "")
++ builder.CreateCall(trap.GlobalValueType(), trap, nil, "")
+ }
+ }
+ }
+diff --git a/transform/rtcalls.go b/transform/rtcalls.go
+index 2edfd655..2f17f815 100644
+--- a/transform/rtcalls.go
++++ b/transform/rtcalls.go
+@@ -165,7 +165,7 @@ func OptimizeReflectImplements(mod llvm.Module) {
+
+ // Replace Implements call with the type assert call.
+ builder.SetInsertPointBefore(call)
+- implements := builder.CreateCall(typeAssertFunction, []llvm.Value{
++ implements := builder.CreateCall(typeAssertFunction.GlobalValueType(),
typeAssertFunction, []llvm.Value{
+ builder.CreatePtrToInt(call.Operand(0), uintptrType, ""), // typecode to
check
+ }, "")
+ call.ReplaceAllUsesWith(implements)
+diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go
+index aeba713d..aedad71d 100644
+--- a/transform/wasm-abi.go
++++ b/transform/wasm-abi.go
+@@ -124,12 +124,12 @@ func ExternalInt64AsPtr(mod llvm.Module, config
*compileopts.Config) error {
+ // Pass a stack-allocated pointer as the first parameter
+ // where the return value should be stored, instead of using
+ // the regular return value.
+- builder.CreateCall(externalFn, callParams, callName)
++ builder.CreateCall(externalFnType, externalFn, callParams, callName)
+ returnValue := builder.CreateLoad(retvalAlloca, "retval")
+ call.ReplaceAllUsesWith(returnValue)
+ call.EraseFromParentAsInstruction()
+ } else {
+- newCall := builder.CreateCall(externalFn, callParams, callName)
++ newCall := builder.CreateCall(externalFnType, externalFn, callParams, callName)
+ call.ReplaceAllUsesWith(newCall)
+ call.EraseFromParentAsInstruction()
+ }
+@@ -156,7 +156,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config)
error {
+ }
+ callParams = append(callParams, paramValue)
+ }
+- retval := builder.CreateCall(fn, callParams, "")
++ retval := builder.CreateCall(fn.GlobalValueType(), fn, callParams, "")
+ if retval.Type().TypeKind() == llvm.VoidTypeKind {
+ builder.CreateRetVoid()
+ } else {
+--
+2.36.1
+
diff --git a/0010-all-add-type-parameter-to-CreateLoad.patch
b/0010-all-add-type-parameter-to-CreateLoad.patch
new file mode 100644
index 0000000..2cbfe1b
--- /dev/null
+++ b/0010-all-add-type-parameter-to-CreateLoad.patch
@@ -0,0 +1,377 @@
+From 65a18179d8ff911ba43a3a28ffb2f36c262cff5e Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Wed, 21 Sep 2022 13:55:32 +0200
+Subject: [PATCH 10/18] all: add type parameter to CreateLoad
+
+This is needed for LLVM 15.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ compiler/atomic.go | 2 +-
+ compiler/channel.go | 8 ++++----
+ compiler/compiler.go | 13 +++++++------
+ compiler/defer.go | 19 +++++++++++--------
+ compiler/llvmutil/wordpack.go | 4 ++--
+ compiler/map.go | 6 +++---
+ compiler/volatile.go | 5 ++++-
+ go.mod | 2 +-
+ go.sum | 4 ++--
+ interp/interpreter.go | 2 +-
+ transform/gc.go | 2 +-
+ transform/stacksize.go | 13 +++++++++----
+ transform/wasm-abi.go | 4 ++--
+ 13 files changed, 48 insertions(+), 36 deletions(-)
+
+diff --git a/compiler/atomic.go b/compiler/atomic.go
+index 6ba3849c..73761be4 100644
+--- a/compiler/atomic.go
++++ b/compiler/atomic.go
+@@ -56,7 +56,7 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
+ return swapped
+ case "LoadInt32", "LoadInt64", "LoadUint32",
"LoadUint64", "LoadUintptr", "LoadPointer":
+ ptr := b.getValue(b.fn.Params[0])
+- val := b.CreateLoad(ptr, "")
++ val := b.CreateLoad(b.getLLVMType(b.fn.Signature.Results().At(0).Type()), ptr,
"")
+ val.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent)
+ val.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required
+ return val
+diff --git a/compiler/channel.go b/compiler/channel.go
+index a9886e10..5c3b6c59 100644
+--- a/compiler/channel.go
++++ b/compiler/channel.go
+@@ -84,7 +84,7 @@ func (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value {
+ if isZeroSize {
+ received = llvm.ConstNull(valueType)
+ } else {
+- received = b.CreateLoad(valueAlloca, "chan.received")
++ received = b.CreateLoad(valueType, valueAlloca, "chan.received")
+ b.emitLifetimeEnd(valueAllocaCast, valueAllocaSize)
+ }
+ b.emitLifetimeEnd(channelBlockedListAllocaCast, channelBlockedListAllocaSize)
+@@ -264,8 +264,8 @@ func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value
{
+ // receive can proceed at a time) so we'll get that alloca, bitcast
+ // it to the correct type, and dereference it.
+ recvbuf := b.selectRecvBuf[expr.Tuple.(*ssa.Select)]
+- typ := llvm.PointerType(b.getLLVMType(expr.Type()), 0)
+- ptr := b.CreateBitCast(recvbuf, typ, "")
+- return b.CreateLoad(ptr, "")
++ typ := b.getLLVMType(expr.Type())
++ ptr := b.CreateBitCast(recvbuf, llvm.PointerType(typ, 0), "")
++ return b.CreateLoad(typ, ptr, "")
+ }
+ }
+diff --git a/compiler/compiler.go b/compiler/compiler.go
+index b64fddcc..7ab2fe4e 100644
+--- a/compiler/compiler.go
++++ b/compiler/compiler.go
+@@ -1931,11 +1931,12 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error)
{
+
+ // Can't load directly from array (as index is non-constant), so have to
+ // do it using an alloca+gep+load.
+- alloca, allocaPtr, allocaSize := b.createTemporaryAlloca(array.Type(),
"index.alloca")
++ arrayType := array.Type()
++ alloca, allocaPtr, allocaSize := b.createTemporaryAlloca(arrayType,
"index.alloca")
+ b.CreateStore(array, alloca)
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ ptr := b.CreateInBoundsGEP(alloca, []llvm.Value{zero, index}, "index.gep")
+- result := b.CreateLoad(ptr, "index.load")
++ result := b.CreateLoad(arrayType.ElementType(), ptr, "index.load")
+ b.emitLifetimeEnd(allocaPtr, allocaSize)
+ return result, nil
+ case *ssa.IndexAddr:
+@@ -2012,7 +2013,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ // Lookup byte
+ buf := b.CreateExtractValue(value, 0, "")
+ bufPtr := b.CreateInBoundsGEP(buf, []llvm.Value{index}, "")
+- return b.CreateLoad(bufPtr, ""), nil
++ return b.CreateLoad(b.ctx.Int8Type(), bufPtr, ""), nil
+ case *types.Map:
+ valueType := expr.Type()
+ if expr.CommaOk {
+@@ -3076,10 +3077,10 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error)
{
+ return llvm.Value{}, b.makeError(unop.Pos(), "todo: unknown type for negate:
"+unop.X.Type().Underlying().String())
+ }
+ case token.MUL: // *x, dereference pointer
+- unop.X.Type().Underlying().(*types.Pointer).Elem()
++ valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem())
+ if b.targetData.TypeAllocSize(x.Type().ElementType()) == 0 {
+ // zero-length data
+- return llvm.ConstNull(x.Type().ElementType()), nil
++ return llvm.ConstNull(valueType), nil
+ } else if strings.HasSuffix(unop.X.String(), "$funcaddr") {
+ // CGo function pointer. The cgo part has rewritten CGo function
+ // pointers as stub global variables of the form:
+@@ -3094,7 +3095,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
+ return b.CreateBitCast(fn, b.i8ptrType, ""), nil
+ } else {
+ b.createNilCheck(unop.X, x, "deref")
+- load := b.CreateLoad(x, "")
++ load := b.CreateLoad(valueType, x, "")
+ return load, nil
+ }
+ case token.XOR: // ^x, toggle all bits in integer
+diff --git a/compiler/defer.go b/compiler/defer.go
+index e82370fa..1f892e5b 100644
+--- a/compiler/defer.go
++++ b/compiler/defer.go
+@@ -249,7 +249,8 @@ func isInLoop(start *ssa.BasicBlock) bool {
+ func (b *builder) createDefer(instr *ssa.Defer) {
+ // The pointer to the previous defer struct, which we will replace to
+ // make a linked list.
+- next := b.CreateLoad(b.deferPtr, "defer.next")
++ deferType := llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)
++ next := b.CreateLoad(deferType, b.deferPtr, "defer.next")
+
+ var values []llvm.Value
+ valueTypes := []llvm.Type{b.uintptrType, next.Type()}
+@@ -406,6 +407,8 @@ func (b *builder) createDefer(instr *ssa.Defer) {
+
+ // createRunDefers emits code to run all deferred functions.
+ func (b *builder) createRunDefers() {
++ deferType := llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)
++
+ // Add a loop like the following:
+ // for stack != nil {
+ // _stack := stack
+@@ -431,7 +434,7 @@ func (b *builder) createRunDefers() {
+ // Create loop head:
+ // for stack != nil {
+ b.SetInsertPointAtEnd(loophead)
+- deferData := b.CreateLoad(b.deferPtr, "")
++ deferData := b.CreateLoad(deferType, b.deferPtr, "")
+ stackIsNil := b.CreateICmp(llvm.IntEQ, deferData,
llvm.ConstPointerNull(deferData.Type()), "stackIsNil")
+ b.CreateCondBr(stackIsNil, end, loop)
+
+@@ -444,13 +447,13 @@ func (b *builder) createRunDefers() {
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), 1, false), // .next field
+ }, "stack.next.gep")
+- nextStack := b.CreateLoad(nextStackGEP, "stack.next")
++ nextStack := b.CreateLoad(deferType, nextStackGEP, "stack.next")
+ b.CreateStore(nextStack, b.deferPtr)
+ gep := b.CreateInBoundsGEP(deferData, []llvm.Value{
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false), // .callback field
+ }, "callback.gep")
+- callback := b.CreateLoad(gep, "callback")
++ callback := b.CreateLoad(b.uintptrType, gep, "callback")
+ sw := b.CreateSwitch(callback, unreachable, len(b.allDeferFuncs))
+
+ for i, callback := range b.allDeferFuncs {
+@@ -487,7 +490,7 @@ func (b *builder) createRunDefers() {
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := 2; i < len(valueTypes); i++ {
+ gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "gep")
+- forwardParam := b.CreateLoad(gep, "param")
++ forwardParam := b.CreateLoad(valueTypes[i], gep, "param")
+ forwardParams = append(forwardParams, forwardParam)
+ }
+
+@@ -536,7 +539,7 @@ func (b *builder) createRunDefers() {
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := range getParams(callback.Signature) {
+ gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
+- forwardParam := b.CreateLoad(gep, "param")
++ forwardParam := b.CreateLoad(valueTypes[i+2], gep, "param")
+ forwardParams = append(forwardParams, forwardParam)
+ }
+
+@@ -569,7 +572,7 @@ func (b *builder) createRunDefers() {
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := 2; i < len(valueTypes); i++ {
+ gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
+- forwardParam := b.CreateLoad(gep, "param")
++ forwardParam := b.CreateLoad(valueTypes[i], gep, "param")
+ forwardParams = append(forwardParams, forwardParam)
+ }
+
+@@ -596,7 +599,7 @@ func (b *builder) createRunDefers() {
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := 0; i < params.Len(); i++ {
+ gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
+- forwardParam := b.CreateLoad(gep, "param")
++ forwardParam := b.CreateLoad(valueTypes[i+2], gep, "param")
+ argValues = append(argValues, forwardParam)
+ }
+
+diff --git a/compiler/llvmutil/wordpack.go b/compiler/llvmutil/wordpack.go
+index 73b1e27e..97b86045 100644
+--- a/compiler/llvmutil/wordpack.go
++++ b/compiler/llvmutil/wordpack.go
+@@ -63,7 +63,7 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix
string, needs
+ }
+
+ // Load value (the *i8) from the alloca.
+- result := builder.CreateLoad(packedAlloc, "")
++ result := builder.CreateLoad(i8ptrType, packedAlloc, "")
+
+ // End the lifetime of the alloca, to help the optimizer.
+ packedPtr := builder.CreateBitCast(packedAlloc, i8ptrType, "")
+@@ -171,7 +171,7 @@ func EmitPointerUnpack(builder llvm.Builder, mod llvm.Module, ptr
llvm.Value, va
+ llvm.ConstInt(ctx.Int32Type(), uint64(i), false),
+ }
+ gep := builder.CreateInBoundsGEP(packedAlloc, indices, "")
+- values[i] = builder.CreateLoad(gep, "")
++ values[i] = builder.CreateLoad(valueType, gep, "")
+ }
+ if !packedRawAlloc.IsNil() {
+ allocPtr := builder.CreateBitCast(packedRawAlloc, i8ptrType, "")
+diff --git a/compiler/map.go b/compiler/map.go
+index 57a7033a..7655ec70 100644
+--- a/compiler/map.go
++++ b/compiler/map.go
+@@ -106,7 +106,7 @@ func (b *builder) createMapLookup(keyType, valueType types.Type, m,
key llvm.Val
+
+ // Load the resulting value from the hashmap. The value is set to the zero
+ // value if the key doesn't exist in the hashmap.
+- mapValue := b.CreateLoad(mapValueAlloca, "")
++ mapValue := b.CreateLoad(llvmValueType, mapValueAlloca, "")
+ b.emitLifetimeEnd(mapValuePtr, mapValueAllocaSize)
+
+ if commaOk {
+@@ -217,8 +217,8 @@ func (b *builder) createMapIteratorNext(rangeVal ssa.Value,
llvmRangeVal, it llv
+ mapKeyAlloca, mapKeyPtr, mapKeySize := b.createTemporaryAlloca(llvmStoredKeyType,
"range.key")
+ mapValueAlloca, mapValuePtr, mapValueSize := b.createTemporaryAlloca(llvmValueType,
"range.value")
+ ok := b.createRuntimeCall("hashmapNext", []llvm.Value{llvmRangeVal, it,
mapKeyPtr, mapValuePtr}, "range.next")
+- mapKey := b.CreateLoad(mapKeyAlloca, "")
+- mapValue := b.CreateLoad(mapValueAlloca, "")
++ mapKey := b.CreateLoad(llvmStoredKeyType, mapKeyAlloca, "")
++ mapValue := b.CreateLoad(llvmValueType, mapValueAlloca, "")
+
+ if isKeyStoredAsInterface {
+ // The key is stored as an interface but it isn't of interface type.
+diff --git a/compiler/volatile.go b/compiler/volatile.go
+index 143eff28..3d3a67fa 100644
+--- a/compiler/volatile.go
++++ b/compiler/volatile.go
+@@ -1,5 +1,7 @@
+ package compiler
+
++import "go/types"
++
+ // This file implements volatile loads/stores in runtime/volatile.LoadT and
+ // runtime/volatile.StoreT as compiler builtins.
+
+@@ -9,7 +11,8 @@ func (b *builder) createVolatileLoad() {
+ b.createFunctionStart(true)
+ addr := b.getValue(b.fn.Params[0])
+ b.createNilCheck(b.fn.Params[0], addr, "deref")
+- val := b.CreateLoad(addr, "")
++ valType := b.getLLVMType(b.fn.Params[0].Type().(*types.Pointer).Elem())
++ val := b.CreateLoad(valType, addr, "")
+ val.SetVolatile(true)
+ b.CreateRet(val)
+ }
+diff --git a/go.mod b/go.mod
+index 4af10427..26707a96 100644
+--- a/go.mod
++++ b/go.mod
+@@ -17,7 +17,7 @@ require (
+
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
+
golang.org/x/tools v0.1.11
+ gopkg.in/yaml.v2 v2.4.0
+-
tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636
++
tinygo.org/x/go-llvm v0.0.0-20220921144624-6c125b0aeda6
+ )
+
+ require (
+diff --git a/go.sum b/go.sum
+index 401de3be..e5c734cd 100644
+--- a/go.sum
++++ b/go.sum
+@@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod
h1:Co6ibVJAznAaIkqp8
+ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+-tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636
h1:JxtI6P/lyWHAcs/4QJWeWIbh4HntxPFONMVWvx7wf8Y=
+-tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
++tinygo.org/x/go-llvm v0.0.0-20220921144624-6c125b0aeda6
h1:bJYUpmJrVm7Uluxh80qSivfeU3d9D4JNg5oJ+h9U+xc=
++tinygo.org/x/go-llvm v0.0.0-20220921144624-6c125b0aeda6/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+diff --git a/interp/interpreter.go b/interp/interpreter.go
+index 4a4553f8..2c7fd8c3 100644
+--- a/interp/interpreter.go
++++ b/interp/interpreter.go
+@@ -983,7 +983,7 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals
[]value, me
+ if err != nil {
+ return r.errorAt(inst, err)
+ }
+- result = r.builder.CreateLoad(operands[0], inst.name)
++ result = r.builder.CreateLoad(inst.llvmInst.Type(), operands[0], inst.name)
+ if inst.llvmInst.IsVolatile() {
+ result.SetVolatile(true)
+ }
+diff --git a/transform/gc.go b/transform/gc.go
+index 87dc6e88..7a4e99ac 100644
+--- a/transform/gc.go
++++ b/transform/gc.go
+@@ -222,7 +222,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ builder.CreateStore(initialStackObject, stackObject)
+
+ // Update stack start.
+- parent := builder.CreateLoad(stackChainStart, "")
++ parent := builder.CreateLoad(stackChainStartType, stackChainStart, "")
+ gep := builder.CreateGEP(stackObject, []llvm.Value{
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+diff --git a/transform/stacksize.go b/transform/stacksize.go
+index 7be49238..f1a3c93d 100644
+--- a/transform/stacksize.go
++++ b/transform/stacksize.go
+@@ -34,6 +34,11 @@ func CreateStackSizeLoads(mod llvm.Module, config *compileopts.Config)
[]string
+ return nil
+ }
+
++ ctx := mod.Context()
++ targetData := llvm.NewTargetData(mod.DataLayout())
++ defer targetData.Dispose()
++ uintptrType := ctx.IntType(targetData.PointerSize() * 8)
++
+ // Create the new global with stack sizes, that will be put in a new section
+ // just for itself.
+ stackSizesGlobalType := llvm.ArrayType(functions[0].Type(), len(functions))
+@@ -50,16 +55,16 @@ func CreateStackSizeLoads(mod llvm.Module, config
*compileopts.Config) []string
+ appendToUsedGlobals(mod, append([]llvm.Value{stackSizesGlobal}, functionValues...)...)
+
+ // Replace the calls with loads from the new global with stack sizes.
+- irbuilder := mod.Context().NewBuilder()
++ irbuilder := ctx.NewBuilder()
+ defer irbuilder.Dispose()
+ for i, function := range functions {
+ for _, use := range functionMap[function] {
+ ptr := llvm.ConstGEP(stackSizesGlobal, []llvm.Value{
+- llvm.ConstInt(mod.Context().Int32Type(), 0, false),
+- llvm.ConstInt(mod.Context().Int32Type(), uint64(i), false),
++ llvm.ConstInt(ctx.Int32Type(), 0, false),
++ llvm.ConstInt(ctx.Int32Type(), uint64(i), false),
+ })
+ irbuilder.SetInsertPointBefore(use)
+- stacksize := irbuilder.CreateLoad(ptr, "stacksize")
++ stacksize := irbuilder.CreateLoad(uintptrType, ptr, "stacksize")
+ use.ReplaceAllUsesWith(stacksize)
+ use.EraseFromParentAsInstruction()
+ }
+diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go
+index aedad71d..064e38f4 100644
+--- a/transform/wasm-abi.go
++++ b/transform/wasm-abi.go
+@@ -125,7 +125,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config)
error {
+ // where the return value should be stored, instead of using
+ // the regular return value.
+ builder.CreateCall(externalFnType, externalFn, callParams, callName)
+- returnValue := builder.CreateLoad(retvalAlloca, "retval")
++ returnValue := builder.CreateLoad(int64Type, retvalAlloca, "retval")
+ call.ReplaceAllUsesWith(returnValue)
+ call.EraseFromParentAsInstruction()
+ } else {
+@@ -152,7 +152,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config)
error {
+ for i, origParam := range fn.Params() {
+ paramValue := externalFn.Param(i)
+ if origParam.Type() == int64Type {
+- paramValue = builder.CreateLoad(paramValue, "i64")
++ paramValue = builder.CreateLoad(int64Type, paramValue, "i64")
+ }
+ callParams = append(callParams, paramValue)
+ }
+--
+2.36.1
+
diff --git a/0011-all-add-type-parameter-to-GEP-calls.patch
b/0011-all-add-type-parameter-to-GEP-calls.patch
new file mode 100644
index 0000000..866f9fb
--- /dev/null
+++ b/0011-all-add-type-parameter-to-GEP-calls.patch
@@ -0,0 +1,565 @@
+From dd4f1c594ef0fadb59fa418f1049542f86237800 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Wed, 21 Sep 2022 17:00:09 +0200
+Subject: [PATCH 11/18] all: add type parameter to *GEP calls
+
+This is necessary for LLVM 15.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ builder/build.go | 2 +-
+ compiler/channel.go | 8 +++---
+ compiler/compiler.go | 46 ++++++++++++++++++++---------------
+ compiler/defer.go | 19 ++++++++-------
+ compiler/interface.go | 16 ++++++------
+ compiler/llvm.go | 6 ++---
+ compiler/llvmutil/wordpack.go | 6 ++---
+ go.mod | 2 +-
+ go.sum | 4 +--
+ interp/memory.go | 4 +--
+ transform/gc.go | 4 +--
+ transform/llvm.go | 10 ++++----
+ transform/stacksize.go | 2 +-
+ 13 files changed, 69 insertions(+), 60 deletions(-)
+
+diff --git a/builder/build.go b/builder/build.go
+index 28385044..7a7dd9ac 100644
+--- a/builder/build.go
++++ b/builder/build.go
+@@ -1153,7 +1153,7 @@ func setGlobalValues(mod llvm.Module, globals
map[string]map[string]string) erro
+
+ // Create the string value, which is a {ptr, len} pair.
+ zero := llvm.ConstInt(mod.Context().Int32Type(), 0, false)
+- ptr := llvm.ConstGEP(buf, []llvm.Value{zero, zero})
++ ptr := llvm.ConstGEP(bufInitializer.Type(), buf, []llvm.Value{zero, zero})
+ if ptr.Type() != elementTypes[0] {
+ return fmt.Errorf("%s: not a string", globalName)
+ }
+diff --git a/compiler/channel.go b/compiler/channel.go
+index 5c3b6c59..81f84565 100644
+--- a/compiler/channel.go
++++ b/compiler/channel.go
+@@ -173,7 +173,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
+ allocaType := llvm.ArrayType(b.ctx.Int8Type(), int(recvbufSize))
+ recvbufAlloca, _, _ := b.createTemporaryAlloca(allocaType,
"select.recvbuf.alloca")
+ recvbufAlloca.SetAlignment(recvbufAlign)
+- recvbuf = b.CreateGEP(recvbufAlloca, []llvm.Value{
++ recvbuf = b.CreateGEP(allocaType, recvbufAlloca, []llvm.Value{
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ }, "select.recvbuf")
+@@ -184,13 +184,13 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
+ statesAlloca, statesI8, statesSize := b.createTemporaryAlloca(statesAllocaType,
"select.states.alloca")
+ for i, state := range selectStates {
+ // Set each slice element to the appropriate channel.
+- gep := b.CreateGEP(statesAlloca, []llvm.Value{
++ gep := b.CreateGEP(statesAllocaType, statesAlloca, []llvm.Value{
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
+ }, "")
+ b.CreateStore(state, gep)
+ }
+- statesPtr := b.CreateGEP(statesAlloca, []llvm.Value{
++ statesPtr := b.CreateGEP(statesAllocaType, statesAlloca, []llvm.Value{
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ }, "select.states")
+@@ -204,7 +204,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
+ chBlockAllocaType :=
llvm.ArrayType(b.getLLVMRuntimeType("channelBlockedList"), len(selectStates))
+ chBlockAlloca, chBlockAllocaPtr, chBlockSize :=
b.createTemporaryAlloca(chBlockAllocaType, "select.block.alloca")
+ chBlockLen := llvm.ConstInt(b.uintptrType, uint64(len(selectStates)), false)
+- chBlockPtr := b.CreateGEP(chBlockAlloca, []llvm.Value{
++ chBlockPtr := b.CreateGEP(chBlockAllocaType, chBlockAlloca, []llvm.Value{
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ }, "select.block")
+diff --git a/compiler/compiler.go b/compiler/compiler.go
+index 7ab2fe4e..c93b2e56 100644
+--- a/compiler/compiler.go
++++ b/compiler/compiler.go
+@@ -918,7 +918,7 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global,
global llvm.Valu
+ bufferGlobal.SetInitializer(bufferValue)
+ bufferGlobal.SetLinkage(llvm.InternalLinkage)
+ bufferGlobal.SetAlignment(1)
+- slicePtr := llvm.ConstInBoundsGEP(bufferGlobal, []llvm.Value{
++ slicePtr := llvm.ConstInBoundsGEP(bufferValue.Type(), bufferGlobal, []llvm.Value{
+ llvm.ConstInt(c.uintptrType, 0, false),
+ llvm.ConstInt(c.uintptrType, 0, false),
+ })
+@@ -990,7 +990,7 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global,
global llvm.Valu
+ // Create the slice object itself.
+ // Because embed.FS refers to it as *[]embed.file instead of a plain
+ // []embed.file, we have to store this as a global.
+- slicePtr := llvm.ConstInBoundsGEP(sliceDataGlobal, []llvm.Value{
++ slicePtr := llvm.ConstInBoundsGEP(sliceDataInitializer.Type(), sliceDataGlobal,
[]llvm.Value{
+ llvm.ConstInt(c.uintptrType, 0, false),
+ llvm.ConstInt(c.uintptrType, 0, false),
+ })
+@@ -1018,11 +1018,11 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global,
global llvm.Valu
+ func (c *compilerContext) getEmbedFileString(file *loader.EmbedFile) llvm.Value {
+ dataGlobalName := "embed/file_" + file.Hash
+ dataGlobal := c.mod.NamedGlobal(dataGlobalName)
++ dataGlobalType := llvm.ArrayType(c.ctx.Int8Type(), int(file.Size))
+ if dataGlobal.IsNil() {
+- dataGlobalType := llvm.ArrayType(c.ctx.Int8Type(), int(file.Size))
+ dataGlobal = llvm.AddGlobal(c.mod, dataGlobalType, dataGlobalName)
+ }
+- strPtr := llvm.ConstInBoundsGEP(dataGlobal, []llvm.Value{
++ strPtr := llvm.ConstInBoundsGEP(dataGlobalType, dataGlobal, []llvm.Value{
+ llvm.ConstInt(c.uintptrType, 0, false),
+ llvm.ConstInt(c.uintptrType, 0, false),
+ })
+@@ -1601,7 +1601,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues
[]llvm.Value, c
+ // Note: the pointer is always of type *i8.
+ ptr := argValues[0]
+ len := argValues[1]
+- return b.CreateGEP(ptr, []llvm.Value{len}, ""), nil
++ return b.CreateGEP(b.ctx.Int8Type(), ptr, []llvm.Value{len}, ""), nil
+ case "Alignof": // unsafe.Alignof
+ align := b.targetData.ABITypeAlignment(argValues[0].Type())
+ return llvm.ConstInt(b.uintptrType, uint64(align), false), nil
+@@ -1911,7 +1911,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), uint64(expr.Field), false),
+ }
+- return b.CreateInBoundsGEP(val, indices, ""), nil
++ elementType := b.getLLVMType(expr.X.Type().Underlying().(*types.Pointer).Elem())
++ return b.CreateInBoundsGEP(elementType, val, indices, ""), nil
+ case *ssa.Function:
+ panic("function is not an expression")
+ case *ssa.Global:
+@@ -1935,7 +1936,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ alloca, allocaPtr, allocaSize := b.createTemporaryAlloca(arrayType,
"index.alloca")
+ b.CreateStore(array, alloca)
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+- ptr := b.CreateInBoundsGEP(alloca, []llvm.Value{zero, index}, "index.gep")
++ ptr := b.CreateInBoundsGEP(arrayType, alloca, []llvm.Value{zero, index},
"index.gep")
+ result := b.CreateLoad(arrayType.ElementType(), ptr, "index.load")
+ b.emitLifetimeEnd(allocaPtr, allocaSize)
+ return result, nil
+@@ -1945,13 +1946,15 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error)
{
+
+ // Get buffer pointer and length
+ var bufptr, buflen llvm.Value
++ var bufType llvm.Type
+ switch ptrTyp := expr.X.Type().Underlying().(type) {
+ case *types.Pointer:
+- typ := expr.X.Type().Underlying().(*types.Pointer).Elem().Underlying()
++ typ := ptrTyp.Elem().Underlying()
+ switch typ := typ.(type) {
+ case *types.Array:
+ bufptr = val
+ buflen = llvm.ConstInt(b.uintptrType, uint64(typ.Len()), false)
++ bufType = b.getLLVMType(typ)
+ // Check for nil pointer before calculating the address, from
+ // the spec:
+ // > For an operand x of type T, the address operation &x
+@@ -1965,6 +1968,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ case *types.Slice:
+ bufptr = b.CreateExtractValue(val, 0, "indexaddr.ptr")
+ buflen = b.CreateExtractValue(val, 1, "indexaddr.len")
++ bufType = b.getLLVMType(ptrTyp.Elem())
+ default:
+ return llvm.Value{}, b.makeError(expr.Pos(), "todo: indexaddr:
"+ptrTyp.String())
+ }
+@@ -1982,9 +1986,9 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ index,
+ }
+- return b.CreateInBoundsGEP(bufptr, indices, ""), nil
++ return b.CreateInBoundsGEP(bufType, bufptr, indices, ""), nil
+ case *types.Slice:
+- return b.CreateInBoundsGEP(bufptr, []llvm.Value{index}, ""), nil
++ return b.CreateInBoundsGEP(bufType, bufptr, []llvm.Value{index}, ""), nil
+ default:
+ panic("unreachable")
+ }
+@@ -2012,8 +2016,9 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+
+ // Lookup byte
+ buf := b.CreateExtractValue(value, 0, "")
+- bufPtr := b.CreateInBoundsGEP(buf, []llvm.Value{index}, "")
+- return b.CreateLoad(b.ctx.Int8Type(), bufPtr, ""), nil
++ bufElemType := b.ctx.Int8Type()
++ bufPtr := b.CreateInBoundsGEP(bufElemType, buf, []llvm.Value{index}, "")
++ return b.CreateLoad(bufElemType, bufPtr, ""), nil
+ case *types.Map:
+ valueType := expr.Type()
+ if expr.CommaOk {
+@@ -2146,7 +2151,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ switch typ := expr.X.Type().Underlying().(type) {
+ case *types.Pointer: // pointer to array
+ // slice an array
+- length := typ.Elem().Underlying().(*types.Array).Len()
++ arrayType := typ.Elem().Underlying().(*types.Array)
++ length := arrayType.Len()
+ llvmLen := llvm.ConstInt(b.uintptrType, uint64(length), false)
+ if high.IsNil() {
+ high = llvmLen
+@@ -2175,7 +2181,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ }
+
+ sliceLen := b.CreateSub(high, low, "slice.len")
+- slicePtr := b.CreateInBoundsGEP(value, indices, "slice.ptr")
++ slicePtr := b.CreateInBoundsGEP(b.getLLVMType(arrayType), value, indices,
"slice.ptr")
+ sliceCap := b.CreateSub(max, low, "slice.cap")
+
+ slice := b.ctx.ConstStruct([]llvm.Value{
+@@ -2214,7 +2220,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ max = b.CreateTrunc(max, b.uintptrType, "")
+ }
+
+- newPtr := b.CreateInBoundsGEP(oldPtr, []llvm.Value{low}, "")
++ ptrElemType := b.getLLVMType(typ.Elem())
++ newPtr := b.CreateInBoundsGEP(ptrElemType, oldPtr, []llvm.Value{low}, "")
+ newLen := b.CreateSub(high, low, "")
+ newCap := b.CreateSub(max, low, "")
+ slice := b.ctx.ConstStruct([]llvm.Value{
+@@ -2254,7 +2261,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
+ high = b.CreateTrunc(high, b.uintptrType, "")
+ }
+
+- newPtr := b.CreateInBoundsGEP(oldPtr, []llvm.Value{low}, "")
++ newPtr := b.CreateInBoundsGEP(b.ctx.Int8Type(), oldPtr, []llvm.Value{low},
"")
+ newLen := b.CreateSub(high, low, "")
+ str := llvm.Undef(b.getLLVMRuntimeType("_string"))
+ str = b.CreateInsertValue(str, newPtr, 0, "")
+@@ -2717,14 +2724,15 @@ func (c *compilerContext) createConst(expr *ssa.Const) llvm.Value
{
+ var strPtr llvm.Value
+ if str != "" {
+ objname := c.pkg.Path() + "$string"
+- global := llvm.AddGlobal(c.mod, llvm.ArrayType(c.ctx.Int8Type(), len(str)),
objname)
++ globalType := llvm.ArrayType(c.ctx.Int8Type(), len(str))
++ global := llvm.AddGlobal(c.mod, globalType, objname)
+ global.SetInitializer(c.ctx.ConstString(str, false))
+ global.SetLinkage(llvm.InternalLinkage)
+ global.SetGlobalConstant(true)
+ global.SetUnnamedAddr(true)
+ global.SetAlignment(1)
+ zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
+- strPtr = llvm.ConstInBoundsGEP(global, []llvm.Value{zero, zero})
++ strPtr = llvm.ConstInBoundsGEP(globalType, global, []llvm.Value{zero, zero})
+ } else {
+ strPtr = llvm.ConstNull(c.i8ptrType)
+ }
+@@ -2844,7 +2852,7 @@ func (b *builder) createConvert(typeFrom, typeTo types.Type, value
llvm.Value, p
+ // create a GEP that is not in bounds. However, we're
+ // talking about unsafe code here so the programmer has to
+ // be careful anyway.
+- return b.CreateInBoundsGEP(origptr, []llvm.Value{index}, ""), nil
++ return b.CreateInBoundsGEP(b.ctx.Int8Type(), origptr, []llvm.Value{index},
""), nil
+ }
+ }
+ }
+diff --git a/compiler/defer.go b/compiler/defer.go
+index 1f892e5b..27e90331 100644
+--- a/compiler/defer.go
++++ b/compiler/defer.go
+@@ -407,7 +407,8 @@ func (b *builder) createDefer(instr *ssa.Defer) {
+
+ // createRunDefers emits code to run all deferred functions.
+ func (b *builder) createRunDefers() {
+- deferType := llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)
++ deferType := b.getLLVMRuntimeType("_defer")
++ deferPtrType := llvm.PointerType(deferType, 0)
+
+ // Add a loop like the following:
+ // for stack != nil {
+@@ -434,7 +435,7 @@ func (b *builder) createRunDefers() {
+ // Create loop head:
+ // for stack != nil {
+ b.SetInsertPointAtEnd(loophead)
+- deferData := b.CreateLoad(deferType, b.deferPtr, "")
++ deferData := b.CreateLoad(deferPtrType, b.deferPtr, "")
+ stackIsNil := b.CreateICmp(llvm.IntEQ, deferData,
llvm.ConstPointerNull(deferData.Type()), "stackIsNil")
+ b.CreateCondBr(stackIsNil, end, loop)
+
+@@ -443,13 +444,13 @@ func (b *builder) createRunDefers() {
+ // stack = stack.next
+ // switch stack.callback {
+ b.SetInsertPointAtEnd(loop)
+- nextStackGEP := b.CreateInBoundsGEP(deferData, []llvm.Value{
++ nextStackGEP := b.CreateInBoundsGEP(deferType, deferData, []llvm.Value{
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), 1, false), // .next field
+ }, "stack.next.gep")
+- nextStack := b.CreateLoad(deferType, nextStackGEP, "stack.next")
++ nextStack := b.CreateLoad(deferPtrType, nextStackGEP, "stack.next")
+ b.CreateStore(nextStack, b.deferPtr)
+- gep := b.CreateInBoundsGEP(deferData, []llvm.Value{
++ gep := b.CreateInBoundsGEP(deferType, deferData, []llvm.Value{
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(b.ctx.Int32Type(), 0, false), // .callback field
+ }, "callback.gep")
+@@ -489,7 +490,7 @@ func (b *builder) createRunDefers() {
+ forwardParams := []llvm.Value{}
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := 2; i < len(valueTypes); i++ {
+- gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "gep")
++ gep := b.CreateInBoundsGEP(deferredCallType, deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "gep")
+ forwardParam := b.CreateLoad(valueTypes[i], gep, "param")
+ forwardParams = append(forwardParams, forwardParam)
+ }
+@@ -538,7 +539,7 @@ func (b *builder) createRunDefers() {
+ forwardParams := []llvm.Value{}
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := range getParams(callback.Signature) {
+- gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
++ gep := b.CreateInBoundsGEP(deferredCallType, deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
+ forwardParam := b.CreateLoad(valueTypes[i+2], gep, "param")
+ forwardParams = append(forwardParams, forwardParam)
+ }
+@@ -571,7 +572,7 @@ func (b *builder) createRunDefers() {
+ forwardParams := []llvm.Value{}
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := 2; i < len(valueTypes); i++ {
+- gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
++ gep := b.CreateInBoundsGEP(deferredCallType, deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
+ forwardParam := b.CreateLoad(valueTypes[i], gep, "param")
+ forwardParams = append(forwardParams, forwardParam)
+ }
+@@ -598,7 +599,7 @@ func (b *builder) createRunDefers() {
+ var argValues []llvm.Value
+ zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
+ for i := 0; i < params.Len(); i++ {
+- gep := b.CreateInBoundsGEP(deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
++ gep := b.CreateInBoundsGEP(deferredCallType, deferredCallPtr, []llvm.Value{zero,
llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
+ forwardParam := b.CreateLoad(valueTypes[i+2], gep, "param")
+ argValues = append(argValues, forwardParam)
+ }
+diff --git a/compiler/interface.go b/compiler/interface.go
+index 72f8952d..acb474f5 100644
+--- a/compiler/interface.go
++++ b/compiler/interface.go
+@@ -122,19 +122,19 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct)
llvm.Value {
+ for i := 0; i < typ.NumFields(); i++ {
+ fieldGlobalValue := llvm.ConstNull(runtimeStructField)
+ fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue,
c.getTypeCode(typ.Field(i).Type()), []uint32{0})
+- fieldName := c.makeGlobalArray([]byte(typ.Field(i).Name()),
"reflect/types.structFieldName", c.ctx.Int8Type())
++ fieldNameType, fieldName := c.makeGlobalArray([]byte(typ.Field(i).Name()),
"reflect/types.structFieldName", c.ctx.Int8Type())
+ fieldName.SetLinkage(llvm.PrivateLinkage)
+ fieldName.SetUnnamedAddr(true)
+- fieldName = llvm.ConstGEP(fieldName, []llvm.Value{
++ fieldName = llvm.ConstGEP(fieldNameType, fieldName, []llvm.Value{
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ })
+ fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldName, []uint32{1})
+ if typ.Tag(i) != "" {
+- fieldTag := c.makeGlobalArray([]byte(typ.Tag(i)),
"reflect/types.structFieldTag", c.ctx.Int8Type())
++ fieldTagType, fieldTag := c.makeGlobalArray([]byte(typ.Tag(i)),
"reflect/types.structFieldTag", c.ctx.Int8Type())
+ fieldTag.SetLinkage(llvm.PrivateLinkage)
+ fieldTag.SetUnnamedAddr(true)
+- fieldTag = llvm.ConstGEP(fieldTag, []llvm.Value{
++ fieldTag = llvm.ConstGEP(fieldTagType, fieldTag, []llvm.Value{
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ })
+@@ -239,7 +239,7 @@ func (c *compilerContext) getTypeMethodSet(typ types.Type) llvm.Value
{
+ zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
+ if !global.IsNil() {
+ // the method set already exists
+- return llvm.ConstGEP(global, []llvm.Value{zero, zero})
++ return llvm.ConstGEP(global.GlobalValueType(), global, []llvm.Value{zero, zero})
+ }
+
+ ms := c.program.MethodSets.MethodSet(typ)
+@@ -272,7 +272,7 @@ func (c *compilerContext) getTypeMethodSet(typ types.Type) llvm.Value
{
+ global.SetInitializer(value)
+ global.SetGlobalConstant(true)
+ global.SetLinkage(llvm.LinkOnceODRLinkage)
+- return llvm.ConstGEP(global, []llvm.Value{zero, zero})
++ return llvm.ConstGEP(arrayType, global, []llvm.Value{zero, zero})
+ }
+
+ // getInterfaceMethodSet returns a global variable with the method set of the
+@@ -288,7 +288,7 @@ func (c *compilerContext) getInterfaceMethodSet(typ types.Type)
llvm.Value {
+ zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
+ if !global.IsNil() {
+ // method set already exist, return it
+- return llvm.ConstGEP(global, []llvm.Value{zero, zero})
++ return llvm.ConstGEP(global.GlobalValueType(), global, []llvm.Value{zero, zero})
+ }
+
+ // Every method is a *i8 reference indicating the signature of this method.
+@@ -303,7 +303,7 @@ func (c *compilerContext) getInterfaceMethodSet(typ types.Type)
llvm.Value {
+ global.SetInitializer(value)
+ global.SetGlobalConstant(true)
+ global.SetLinkage(llvm.LinkOnceODRLinkage)
+- return llvm.ConstGEP(global, []llvm.Value{zero, zero})
++ return llvm.ConstGEP(value.Type(), global, []llvm.Value{zero, zero})
+ }
+
+ // getMethodSignatureName returns a unique name (that can be used as the name of
+diff --git a/compiler/llvm.go b/compiler/llvm.go
+index 9540bcc6..686d4d2b 100644
+--- a/compiler/llvm.go
++++ b/compiler/llvm.go
+@@ -61,10 +61,10 @@ func (b *builder) emitPointerUnpack(ptr llvm.Value, valueTypes
[]llvm.Type) []ll
+ }
+
+ // makeGlobalArray creates a new LLVM global with the given name and integers as
+-// contents, and returns the global.
++// contents, and returns the global and initializer type.
+ // Note that it is left with the default linkage etc., you should set
+ // linkage/constant/etc properties yourself.
+-func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType
llvm.Type) llvm.Value {
++func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType
llvm.Type) (llvm.Type, llvm.Value) {
+ globalType := llvm.ArrayType(elementType, len(buf))
+ global := llvm.AddGlobal(c.mod, globalType, name)
+ value := llvm.Undef(globalType)
+@@ -73,7 +73,7 @@ func (c *compilerContext) makeGlobalArray(buf []byte, name string,
elementType l
+ value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false),
[]uint32{uint32(i)})
+ }
+ global.SetInitializer(value)
+- return global
++ return globalType, global
+ }
+
+ // createObjectLayout returns a LLVM value (of type i8*) that describes where
+diff --git a/compiler/llvmutil/wordpack.go b/compiler/llvmutil/wordpack.go
+index 97b86045..2a4607c8 100644
+--- a/compiler/llvmutil/wordpack.go
++++ b/compiler/llvmutil/wordpack.go
+@@ -58,7 +58,7 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix
string, needs
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ llvm.ConstInt(ctx.Int32Type(), uint64(i), false),
+ }
+- gep := builder.CreateInBoundsGEP(packedAllocCast, indices, "")
++ gep := builder.CreateInBoundsGEP(packedType, packedAllocCast, indices, "")
+ builder.CreateStore(value, gep)
+ }
+
+@@ -115,7 +115,7 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix
string, needs
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ llvm.ConstInt(ctx.Int32Type(), uint64(i), false),
+ }
+- gep := builder.CreateInBoundsGEP(packedAlloc, indices, "")
++ gep := builder.CreateInBoundsGEP(packedType, packedAlloc, indices, "")
+ builder.CreateStore(value, gep)
+ }
+
+@@ -170,7 +170,7 @@ func EmitPointerUnpack(builder llvm.Builder, mod llvm.Module, ptr
llvm.Value, va
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ llvm.ConstInt(ctx.Int32Type(), uint64(i), false),
+ }
+- gep := builder.CreateInBoundsGEP(packedAlloc, indices, "")
++ gep := builder.CreateInBoundsGEP(packedType, packedAlloc, indices, "")
+ values[i] = builder.CreateLoad(valueType, gep, "")
+ }
+ if !packedRawAlloc.IsNil() {
+diff --git a/go.mod b/go.mod
+index 26707a96..feb4e0d6 100644
+--- a/go.mod
++++ b/go.mod
+@@ -17,7 +17,7 @@ require (
+
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
+
golang.org/x/tools v0.1.11
+ gopkg.in/yaml.v2 v2.4.0
+-
tinygo.org/x/go-llvm v0.0.0-20220921144624-6c125b0aeda6
++
tinygo.org/x/go-llvm v0.0.0-20220921144624-dabbe3f30634
+ )
+
+ require (
+diff --git a/go.sum b/go.sum
+index e5c734cd..907364f9 100644
+--- a/go.sum
++++ b/go.sum
+@@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod
h1:Co6ibVJAznAaIkqp8
+ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+-tinygo.org/x/go-llvm v0.0.0-20220921144624-6c125b0aeda6
h1:bJYUpmJrVm7Uluxh80qSivfeU3d9D4JNg5oJ+h9U+xc=
+-tinygo.org/x/go-llvm v0.0.0-20220921144624-6c125b0aeda6/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
++tinygo.org/x/go-llvm v0.0.0-20220921144624-dabbe3f30634
h1:hihbmHkJjalV4kGshoCF03P/G4IjoXcNAbzLblXLa/M=
++tinygo.org/x/go-llvm v0.0.0-20220921144624-dabbe3f30634/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+diff --git a/interp/memory.go b/interp/memory.go
+index 3a16b875..2fa6f5cb 100644
+--- a/interp/memory.go
++++ b/interp/memory.go
+@@ -646,8 +646,8 @@ func (v pointerValue) toLLVMValue(llvmType llvm.Type, mem
*memoryView) (llvm.Val
+ if llvmValue.Type() != mem.r.i8ptrType {
+ llvmValue = llvm.ConstBitCast(llvmValue, mem.r.i8ptrType)
+ }
+- llvmValue = llvm.ConstInBoundsGEP(llvmValue, []llvm.Value{
+- llvm.ConstInt(llvmValue.Type().Context().Int32Type(), uint64(v.offset()), false),
++ llvmValue = llvm.ConstInBoundsGEP(mem.r.mod.Context().Int8Type(), llvmValue,
[]llvm.Value{
++ llvm.ConstInt(mem.r.mod.Context().Int32Type(), uint64(v.offset()), false),
+ })
+ }
+
+diff --git a/transform/gc.go b/transform/gc.go
+index 7a4e99ac..3870a6b6 100644
+--- a/transform/gc.go
++++ b/transform/gc.go
+@@ -223,7 +223,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+
+ // Update stack start.
+ parent := builder.CreateLoad(stackChainStartType, stackChainStart, "")
+- gep := builder.CreateGEP(stackObject, []llvm.Value{
++ gep := builder.CreateGEP(stackObjectType, stackObject, []llvm.Value{
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ }, "")
+@@ -244,7 +244,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ builder.SetInsertPointBefore(insertionPoint)
+
+ // Extract a pointer to the appropriate section of the stack object.
+- gep := builder.CreateGEP(stackObject, []llvm.Value{
++ gep := builder.CreateGEP(stackObjectType, stackObject, []llvm.Value{
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ llvm.ConstInt(ctx.Int32Type(), uint64(2+i), false),
+ }, "")
+diff --git a/transform/llvm.go b/transform/llvm.go
+index 32ee9560..6716dd63 100644
+--- a/transform/llvm.go
++++ b/transform/llvm.go
+@@ -31,10 +31,10 @@ func hasUses(value llvm.Value) bool {
+ }
+
+ // makeGlobalArray creates a new LLVM global with the given name and integers as
+-// contents, and returns the global.
++// contents, and returns the global and initializer type.
+ // Note that it is left with the default linkage etc., you should set
+ // linkage/constant/etc properties yourself.
+-func makeGlobalArray(mod llvm.Module, bufItf interface{}, name string, elementType
llvm.Type) llvm.Value {
++func makeGlobalArray(mod llvm.Module, bufItf interface{}, name string, elementType
llvm.Type) (llvm.Type, llvm.Value) {
+ buf := reflect.ValueOf(bufItf)
+ globalType := llvm.ArrayType(elementType, buf.Len())
+ global := llvm.AddGlobal(mod, globalType, name)
+@@ -44,7 +44,7 @@ func makeGlobalArray(mod llvm.Module, bufItf interface{}, name string,
elementTy
+ value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false),
[]uint32{uint32(i)})
+ }
+ global.SetInitializer(value)
+- return global
++ return globalType, global
+ }
+
+ // getGlobalBytes returns the slice contained in the array of the provided
+@@ -64,8 +64,8 @@ func getGlobalBytes(global llvm.Value) []byte {
+ // function used for creating reflection sidetables, for example.
+ func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value
{
+ oldGlobal := mod.NamedGlobal(name)
+- global := makeGlobalArray(mod, buf, name+".tmp",
oldGlobal.Type().ElementType())
+- gep := llvm.ConstGEP(global, []llvm.Value{
++ globalType, global := makeGlobalArray(mod, buf, name+".tmp",
oldGlobal.Type().ElementType())
++ gep := llvm.ConstGEP(globalType, global, []llvm.Value{
+ llvm.ConstInt(mod.Context().Int32Type(), 0, false),
+ llvm.ConstInt(mod.Context().Int32Type(), 0, false),
+ })
+diff --git a/transform/stacksize.go b/transform/stacksize.go
+index f1a3c93d..169f1454 100644
+--- a/transform/stacksize.go
++++ b/transform/stacksize.go
+@@ -59,7 +59,7 @@ func CreateStackSizeLoads(mod llvm.Module, config *compileopts.Config)
[]string
+ defer irbuilder.Dispose()
+ for i, function := range functions {
+ for _, use := range functionMap[function] {
+- ptr := llvm.ConstGEP(stackSizesGlobal, []llvm.Value{
++ ptr := llvm.ConstGEP(stackSizesGlobalType, stackSizesGlobal, []llvm.Value{
+ llvm.ConstInt(ctx.Int32Type(), 0, false),
+ llvm.ConstInt(ctx.Int32Type(), uint64(i), false),
+ })
+--
+2.36.1
+
diff --git a/0012-all-replace-llvm.Const-calls-with-builder.Create-cal.patch
b/0012-all-replace-llvm.Const-calls-with-builder.Create-cal.patch
new file mode 100644
index 0000000..a730ef6
--- /dev/null
+++ b/0012-all-replace-llvm.Const-calls-with-builder.Create-cal.patch
@@ -0,0 +1,578 @@
+From 6053c1c8528c63a669d070550bacd43f2f6a68e1 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Tue, 20 Sep 2022 23:26:49 +0200
+Subject: [PATCH 12/18] all: replace llvm.Const* calls with builder.Create*
+ calls
+
+A number of llvm.Const* functions (in particular extractvalue and
+insertvalue) were removed in LLVM 15, so we have to use a builder
+instead. This builder will create the same constant values, it simply
+uses a different API.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ compiler/asserts.go | 2 +-
+ compiler/compiler.go | 23 ++++++++++++++++-------
+ compiler/interface.go | 20 ++++++++++----------
+ compiler/interrupt.go | 8 +++++---
+ compiler/llvm.go | 2 +-
+ interp/interpreter.go | 13 +++++++------
+ interp/memory.go | 8 ++++----
+ transform/gc.go | 2 +-
+ transform/interface-lowering.go | 14 +++++++-------
+ transform/interrupt.go | 7 ++++---
+ transform/llvm.go | 16 +++++++++-------
+ transform/reflect.go | 32 +++++++++++++++++++-------------
+ transform/rtcalls.go | 4 ++--
+ 13 files changed, 86 insertions(+), 65 deletions(-)
+
+diff --git a/compiler/asserts.go b/compiler/asserts.go
+index 8d9efdde..2a5265e9 100644
+--- a/compiler/asserts.go
++++ b/compiler/asserts.go
+@@ -145,7 +145,7 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize
llvm.Value,
+ }
+ // Make the maxBufSize actually the maximum allowed value (in number of
+ // elements in the channel buffer).
+- maxBufSize = llvm.ConstUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize,
false))
++ maxBufSize = b.CreateUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false),
"")
+
+ // Make sure maxBufSize has the same type as bufSize.
+ if maxBufSize.Type() != bufSize.Type() {
+diff --git a/compiler/compiler.go b/compiler/compiler.go
+index c93b2e56..3d29628c 100644
+--- a/compiler/compiler.go
++++ b/compiler/compiler.go
+@@ -63,6 +63,7 @@ type compilerContext struct {
+ DumpSSA bool
+ mod llvm.Module
+ ctx llvm.Context
++ builder llvm.Builder // only used for constant operations
+ dibuilder *llvm.DIBuilder
+ cu llvm.Metadata
+ difiles map[string]llvm.Metadata
+@@ -98,6 +99,7 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine,
config *C
+ }
+
+ c.ctx = llvm.NewContext()
++ c.builder = c.ctx.NewBuilder()
+ c.mod = c.ctx.NewModule(moduleName)
+ c.mod.SetTarget(config.Triple)
+ c.mod.SetDataLayout(c.targetData.String())
+@@ -126,6 +128,12 @@ func newCompilerContext(moduleName string, machine
llvm.TargetMachine, config *C
+ return c
+ }
+
++// Dispose everything related to the context, _except_ for the IR module (and
++// the associated context).
++func (c *compilerContext) dispose() {
++ c.builder.Dispose()
++}
++
+ // builder contains all information relevant to build a single function.
+ type builder struct {
+ *compilerContext
+@@ -256,6 +264,7 @@ func Sizes(machine llvm.TargetMachine) types.Sizes {
+ // CompilePackage compiles a single package to a LLVM module.
+ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine
llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) {
+ c := newCompilerContext(moduleName, machine, config, dumpSSA)
++ defer c.dispose()
+ c.packageDir = pkg.OriginalDir()
+ c.embedGlobals = pkg.EmbedGlobals
+ c.pkg = pkg.Pkg
+@@ -972,10 +981,10 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global,
global llvm.Valu
+ for _, file := range allFiles {
+ fileStruct := llvm.ConstNull(embedFileStructType)
+ name := c.createConst(ssa.NewConst(constant.MakeString(file.Name),
types.Typ[types.String]))
+- fileStruct = llvm.ConstInsertValue(fileStruct, name, []uint32{0}) // "name"
field
++ fileStruct = c.builder.CreateInsertValue(fileStruct, name, 0, "") //
"name" field
+ if file.Hash != "" {
+ data := c.getEmbedFileString(file)
+- fileStruct = llvm.ConstInsertValue(fileStruct, data, []uint32{1}) //
"data" field
++ fileStruct = c.builder.CreateInsertValue(fileStruct, data, 1, "") //
"data" field
+ }
+ fileStructs = append(fileStructs, fileStruct)
+ }
+@@ -1006,7 +1015,7 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global,
global llvm.Valu
+ // Define the embed.FS struct. It has only one field: the files (as a
+ // *[]embed.file).
+ globalInitializer :=
llvm.ConstNull(c.getLLVMType(member.Type().(*types.Pointer).Elem()))
+- globalInitializer = llvm.ConstInsertValue(globalInitializer, sliceGlobal,
[]uint32{0})
++ globalInitializer = c.builder.CreateInsertValue(globalInitializer, sliceGlobal, 0,
"")
+ global.SetInitializer(globalInitializer)
+ global.SetVisibility(llvm.HiddenVisibility)
+ global.SetAlignment(c.targetData.ABITypeAlignment(globalInitializer.Type()))
+@@ -2757,15 +2766,15 @@ func (c *compilerContext) createConst(expr *ssa.Const) llvm.Value
{
+ r := c.createConst(ssa.NewConst(constant.Real(expr.Value),
types.Typ[types.Float32]))
+ i := c.createConst(ssa.NewConst(constant.Imag(expr.Value),
types.Typ[types.Float32]))
+ cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(),
c.ctx.FloatType()}, false))
+- cplx = llvm.ConstInsertValue(cplx, r, []uint32{0})
+- cplx = llvm.ConstInsertValue(cplx, i, []uint32{1})
++ cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
++ cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
+ return cplx
+ } else if typ.Kind() == types.Complex128 {
+ r := c.createConst(ssa.NewConst(constant.Real(expr.Value),
types.Typ[types.Float64]))
+ i := c.createConst(ssa.NewConst(constant.Imag(expr.Value),
types.Typ[types.Float64]))
+ cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(),
c.ctx.DoubleType()}, false))
+- cplx = llvm.ConstInsertValue(cplx, r, []uint32{0})
+- cplx = llvm.ConstInsertValue(cplx, i, []uint32{1})
++ cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
++ cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
+ return cplx
+ } else {
+ panic("unknown constant of basic type: " + expr.String())
+diff --git a/compiler/interface.go b/compiler/interface.go
+index acb474f5..106c327a 100644
+--- a/compiler/interface.go
++++ b/compiler/interface.go
+@@ -88,20 +88,20 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
+ }
+ globalValue := llvm.ConstNull(global.Type().ElementType())
+ if !references.IsNil() {
+- globalValue = llvm.ConstInsertValue(globalValue, references, []uint32{0})
++ globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "")
+ }
+ if length != 0 {
+ lengthValue := llvm.ConstInt(c.uintptrType, uint64(length), false)
+- globalValue = llvm.ConstInsertValue(globalValue, lengthValue, []uint32{1})
++ globalValue = c.builder.CreateInsertValue(globalValue, lengthValue, 1, "")
+ }
+ if !methodSet.IsNil() {
+- globalValue = llvm.ConstInsertValue(globalValue, methodSet, []uint32{2})
++ globalValue = c.builder.CreateInsertValue(globalValue, methodSet, 2, "")
+ }
+ if !ptrTo.IsNil() {
+- globalValue = llvm.ConstInsertValue(globalValue, ptrTo, []uint32{3})
++ globalValue = c.builder.CreateInsertValue(globalValue, ptrTo, 3, "")
+ }
+ if !typeAssert.IsNil() {
+- globalValue = llvm.ConstInsertValue(globalValue, typeAssert, []uint32{4})
++ globalValue = c.builder.CreateInsertValue(globalValue, typeAssert, 4, "")
+ }
+ global.SetInitializer(globalValue)
+ global.SetLinkage(llvm.LinkOnceODRLinkage)
+@@ -121,7 +121,7 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct)
llvm.Value {
+ structGlobalValue := llvm.ConstNull(structGlobalType)
+ for i := 0; i < typ.NumFields(); i++ {
+ fieldGlobalValue := llvm.ConstNull(runtimeStructField)
+- fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue,
c.getTypeCode(typ.Field(i).Type()), []uint32{0})
++ fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue,
c.getTypeCode(typ.Field(i).Type()), 0, "")
+ fieldNameType, fieldName := c.makeGlobalArray([]byte(typ.Field(i).Name()),
"reflect/types.structFieldName", c.ctx.Int8Type())
+ fieldName.SetLinkage(llvm.PrivateLinkage)
+ fieldName.SetUnnamedAddr(true)
+@@ -129,7 +129,7 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct)
llvm.Value {
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ })
+- fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldName, []uint32{1})
++ fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldName, 1,
"")
+ if typ.Tag(i) != "" {
+ fieldTagType, fieldTag := c.makeGlobalArray([]byte(typ.Tag(i)),
"reflect/types.structFieldTag", c.ctx.Int8Type())
+ fieldTag.SetLinkage(llvm.PrivateLinkage)
+@@ -138,13 +138,13 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct)
llvm.Value {
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ llvm.ConstInt(c.ctx.Int32Type(), 0, false),
+ })
+- fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldTag, []uint32{2})
++ fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldTag, 2,
"")
+ }
+ if typ.Field(i).Embedded() {
+ fieldEmbedded := llvm.ConstInt(c.ctx.Int1Type(), 1, false)
+- fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldEmbedded,
[]uint32{3})
++ fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldEmbedded, 3,
"")
+ }
+- structGlobalValue = llvm.ConstInsertValue(structGlobalValue, fieldGlobalValue,
[]uint32{uint32(i)})
++ structGlobalValue = c.builder.CreateInsertValue(structGlobalValue, fieldGlobalValue,
i, "")
+ }
+ structGlobal.SetInitializer(structGlobalValue)
+ structGlobal.SetUnnamedAddr(true)
+diff --git a/compiler/interrupt.go b/compiler/interrupt.go
+index 45c7d074..c1f7d69f 100644
+--- a/compiler/interrupt.go
++++ b/compiler/interrupt.go
+@@ -49,9 +49,11 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon)
(llvm.Value, erro
+ global.SetGlobalConstant(true)
+ global.SetUnnamedAddr(true)
+ initializer := llvm.ConstNull(globalLLVMType)
+- initializer = llvm.ConstInsertValue(initializer, funcContext, []uint32{0})
+- initializer = llvm.ConstInsertValue(initializer, funcPtr, []uint32{1})
+- initializer = llvm.ConstInsertValue(initializer, llvm.ConstInt(b.intType,
uint64(id.Int64()), true), []uint32{2, 0})
++ initializer = b.CreateInsertValue(initializer, funcContext, 0, "")
++ initializer = b.CreateInsertValue(initializer, funcPtr, 1, "")
++ initializer = b.CreateInsertValue(initializer,
llvm.ConstNamedStruct(globalLLVMType.StructElementTypes()[2], []llvm.Value{
++ llvm.ConstInt(b.intType, uint64(id.Int64()), true),
++ }), 2, "")
+ global.SetInitializer(initializer)
+
+ // Add debug info to the interrupt global.
+diff --git a/compiler/llvm.go b/compiler/llvm.go
+index 686d4d2b..8b80869b 100644
+--- a/compiler/llvm.go
++++ b/compiler/llvm.go
+@@ -70,7 +70,7 @@ func (c *compilerContext) makeGlobalArray(buf []byte, name string,
elementType l
+ value := llvm.Undef(globalType)
+ for i := 0; i < len(buf); i++ {
+ ch := uint64(buf[i])
+- value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false),
[]uint32{uint32(i)})
++ value = c.builder.CreateInsertValue(value, llvm.ConstInt(elementType, ch, false), i,
"")
+ }
+ global.SetInitializer(value)
+ return globalType, global
+diff --git a/interp/interpreter.go b/interp/interpreter.go
+index 2c7fd8c3..d029aa33 100644
+--- a/interp/interpreter.go
++++ b/interp/interpreter.go
+@@ -408,7 +408,7 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ // Elem() is only valid for certain type classes.
+ switch class {
+ case "chan", "pointer", "slice", "array":
+- elementType := llvm.ConstExtractValue(typecodeID.Initializer(), []uint32{0})
++ elementType := r.builder.CreateExtractValue(typecodeID.Initializer(), 0,
"")
+ uintptrType := r.mod.Context().IntType(int(mem.r.pointerSize) * 8)
+ locals[inst.localIndex] = r.getValue(llvm.ConstPtrToInt(elementType, uintptrType))
+ default:
+@@ -461,8 +461,8 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ // easier checking in the next step.
+ concreteTypeMethods := map[string]struct{}{}
+ for i := 0; i < methodSet.Type().ArrayLength(); i++ {
+- methodInfo := llvm.ConstExtractValue(methodSet, []uint32{uint32(i)})
+- name := llvm.ConstExtractValue(methodInfo, []uint32{0}).Name()
++ methodInfo := r.builder.CreateExtractValue(methodSet, i, "")
++ name := r.builder.CreateExtractValue(methodInfo, 0, "").Name()
+ concreteTypeMethods[name] = struct{}{}
+ }
+
+@@ -496,7 +496,7 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ typecodeID := typecodeIDBitCast.Operand(0).Initializer()
+
+ // Load the method set, which is part of the typecodeID object.
+- methodSet := llvm.ConstExtractValue(typecodeID,
[]uint32{2}).Operand(0).Initializer()
++ methodSet := r.builder.CreateExtractValue(typecodeID, 2,
"").Operand(0).Initializer()
+
+ // We don't need to load the interface method set.
+
+@@ -511,9 +511,10 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ numMethods := methodSet.Type().ArrayLength()
+ var method llvm.Value
+ for i := 0; i < numMethods; i++ {
+- methodSignature := llvm.ConstExtractValue(methodSet, []uint32{uint32(i), 0})
++ methodSignatureAgg := r.builder.CreateExtractValue(methodSet, i, "")
++ methodSignature := r.builder.CreateExtractValue(methodSignatureAgg, 0,
"")
+ if methodSignature == signature {
+- method = llvm.ConstExtractValue(methodSet, []uint32{uint32(i), 1}).Operand(0)
++ method = r.builder.CreateExtractValue(methodSignatureAgg, 1,
"").Operand(0)
+ }
+ }
+ if method.IsNil() {
+diff --git a/interp/memory.go b/interp/memory.go
+index 2fa6f5cb..583f9355 100644
+--- a/interp/memory.go
++++ b/interp/memory.go
+@@ -215,7 +215,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8)
error {
+ case llvm.StructTypeKind:
+ numElements := llvmType.StructElementTypesCount()
+ for i := 0; i < numElements; i++ {
+- element := llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)})
++ element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
+ err := mv.markExternal(element, mark)
+ if err != nil {
+ return err
+@@ -224,7 +224,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8)
error {
+ case llvm.ArrayTypeKind:
+ numElements := llvmType.ArrayLength()
+ for i := 0; i < numElements; i++ {
+- element := llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)})
++ element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
+ err := mv.markExternal(element, mark)
+ if err != nil {
+ return err
+@@ -1074,7 +1074,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
+ field := rawValue{
+ buf: v.buf[offset:],
+ }
+- field.set(llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}), r)
++ field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r)
+ }
+ case llvm.ArrayTypeKind:
+ numElements := llvmType.ArrayLength()
+@@ -1085,7 +1085,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
+ field := rawValue{
+ buf: v.buf[offset:],
+ }
+- field.set(llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}), r)
++ field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r)
+ }
+ case llvm.DoubleTypeKind:
+ f, _ := llvmValue.DoubleValue()
+diff --git a/transform/gc.go b/transform/gc.go
+index 3870a6b6..514fb1bf 100644
+--- a/transform/gc.go
++++ b/transform/gc.go
+@@ -218,7 +218,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ initialStackObject := llvm.ConstNull(stackObjectType)
+ numSlots := (targetData.TypeAllocSize(stackObjectType) -
uint64(targetData.PointerSize())*2) / uint64(targetData.ABITypeAlignment(uintptrType))
+ numSlotsValue := llvm.ConstInt(uintptrType, numSlots, false)
+- initialStackObject = llvm.ConstInsertValue(initialStackObject, numSlotsValue,
[]uint32{1})
++ initialStackObject = builder.CreateInsertValue(initialStackObject, numSlotsValue, 1,
"")
+ builder.CreateStore(initialStackObject, stackObject)
+
+ // Update stack start.
+diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go
+index f5b29e30..f28443dc 100644
+--- a/transform/interface-lowering.go
++++ b/transform/interface-lowering.go
+@@ -154,7 +154,7 @@ func (p *lowerInterfacesPass) run() error {
+ if initializer.IsNil() {
+ continue
+ }
+- methodSet := llvm.ConstExtractValue(initializer, []uint32{2})
++ methodSet := p.builder.CreateExtractValue(initializer, 2, "")
+ p.addTypeMethods(t, methodSet)
+ }
+ }
+@@ -288,9 +288,9 @@ func (p *lowerInterfacesPass) run() error {
+ zeroUintptr := llvm.ConstNull(p.uintptrType)
+ for _, t := range p.types {
+ initializer := t.typecode.Initializer()
+- methodSet := llvm.ConstExtractValue(initializer, []uint32{2})
+- initializer = llvm.ConstInsertValue(initializer, llvm.ConstNull(methodSet.Type()),
[]uint32{2})
+- initializer = llvm.ConstInsertValue(initializer, zeroUintptr, []uint32{4})
++ methodSet := p.builder.CreateExtractValue(initializer, 2, "")
++ initializer = p.builder.CreateInsertValue(initializer,
llvm.ConstNull(methodSet.Type()), 2, "")
++ initializer = p.builder.CreateInsertValue(initializer, zeroUintptr, 4, "")
+ t.typecode.SetInitializer(initializer)
+ }
+
+@@ -311,10 +311,10 @@ func (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet
llvm.Value)
+ t.methodSet = methodSet
+ set := methodSet.Initializer() // get value from global
+ for i := 0; i < set.Type().ArrayLength(); i++ {
+- methodData := llvm.ConstExtractValue(set, []uint32{uint32(i)})
+- signatureGlobal := llvm.ConstExtractValue(methodData, []uint32{0})
++ methodData := p.builder.CreateExtractValue(set, i, "")
++ signatureGlobal := p.builder.CreateExtractValue(methodData, 0, "")
+ signatureName := signatureGlobal.Name()
+- function := llvm.ConstExtractValue(methodData, []uint32{1}).Operand(0)
++ function := p.builder.CreateExtractValue(methodData, 1, "").Operand(0)
+ signature := p.getSignature(signatureName)
+ method := &methodInfo{
+ function: function,
+diff --git a/transform/interrupt.go b/transform/interrupt.go
+index 2c301be0..b15ff8a9 100644
+--- a/transform/interrupt.go
++++ b/transform/interrupt.go
+@@ -44,7 +44,8 @@ func LowerInterrupts(mod llvm.Module) []error {
+
+ // Get the interrupt number from the initializer
+ initializer := global.Initializer()
+- num := llvm.ConstExtractValue(initializer, []uint32{2, 0}).SExtValue()
++ interrupt := builder.CreateExtractValue(initializer, 2, "")
++ num := builder.CreateExtractValue(interrupt, 0, "").SExtValue()
+ pkg := packageFromInterruptHandle(global)
+
+ handles, exists := handleMap[num]
+@@ -89,8 +90,8 @@ func LowerInterrupts(mod llvm.Module) []error {
+ builder.SetInsertPointBefore(call)
+ for _, handler := range handlers {
+ initializer := handler.Initializer()
+- context := llvm.ConstExtractValue(initializer, []uint32{0})
+- funcPtr := llvm.ConstExtractValue(initializer, []uint32{1}).Operand(0)
++ context := builder.CreateExtractValue(initializer, 0, "")
++ funcPtr := builder.CreateExtractValue(initializer, 1, "").Operand(0)
+ builder.CreateCall(funcPtr.GlobalValueType(), funcPtr, []llvm.Value{
+ num,
+ context,
+diff --git a/transform/llvm.go b/transform/llvm.go
+index 6716dd63..17968f8a 100644
+--- a/transform/llvm.go
++++ b/transform/llvm.go
+@@ -36,25 +36,27 @@ func hasUses(value llvm.Value) bool {
+ // linkage/constant/etc properties yourself.
+ func makeGlobalArray(mod llvm.Module, bufItf interface{}, name string, elementType
llvm.Type) (llvm.Type, llvm.Value) {
+ buf := reflect.ValueOf(bufItf)
+- globalType := llvm.ArrayType(elementType, buf.Len())
+- global := llvm.AddGlobal(mod, globalType, name)
+- value := llvm.Undef(globalType)
++ var values []llvm.Value
+ for i := 0; i < buf.Len(); i++ {
+ ch := buf.Index(i).Uint()
+- value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false),
[]uint32{uint32(i)})
++ values = append(values, llvm.ConstInt(elementType, ch, false))
+ }
++ value := llvm.ConstArray(elementType, values)
++ global := llvm.AddGlobal(mod, value.Type(), name)
+ global.SetInitializer(value)
+- return globalType, global
++ return value.Type(), global
+ }
+
+ // getGlobalBytes returns the slice contained in the array of the provided
+ // global. It can recover the bytes originally created using makeGlobalArray, if
+ // makeGlobalArray was given a byte slice.
+-func getGlobalBytes(global llvm.Value) []byte {
++//
++// The builder parameter is only used for constant operations.
++func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {
+ value := global.Initializer()
+ buf := make([]byte, value.Type().ArrayLength())
+ for i := range buf {
+- buf[i] = byte(llvm.ConstExtractValue(value, []uint32{uint32(i)}).ZExtValue())
++ buf[i] = byte(builder.CreateExtractValue(value, i, "").ZExtValue())
+ }
+ return buf
+ }
+diff --git a/transform/reflect.go b/transform/reflect.go
+index fd70ccb7..68beba9b 100644
+--- a/transform/reflect.go
++++ b/transform/reflect.go
+@@ -76,6 +76,10 @@ var nonBasicTypes = map[string]int64{
+ // typeCodeAssignmentState keeps some global state around for type code
+ // assignments, used to assign one unique type code to each Go type.
+ type typeCodeAssignmentState struct {
++ // Builder used purely for constant operations (because LLVM 15 removed many
++ // llvm.Const* functions).
++ builder llvm.Builder
++
+ // An integer that's incremented each time it's used to give unique IDs to
+ // type codes that are not yet fully supported otherwise by the reflect
+ // package (or are simply unused in the compiled program).
+@@ -165,6 +169,7 @@ func LowerReflect(mod llvm.Module) {
+ defer targetData.Dispose()
+ uintptrType := mod.Context().IntType(targetData.PointerSize() * 8)
+ state := typeCodeAssignmentState{
++ builder: mod.Context().NewBuilder(),
+ fallbackIndex: 1,
+ uintptrLen: targetData.PointerSize() * 8,
+ namedBasicTypes: make(map[string]int),
+@@ -177,6 +182,7 @@ func LowerReflect(mod llvm.Module) {
+ needsStructNamesSidetable:
len(getUses(mod.NamedGlobal("reflect.structNamesSidetable"))) != 0,
+ needsArrayTypesSidetable:
len(getUses(mod.NamedGlobal("reflect.arrayTypesSidetable"))) != 0,
+ }
++ defer state.builder.Dispose()
+ for _, t := range types {
+ num := state.getTypeCodeNum(t.typecode)
+ if num.BitLen() > state.uintptrLen || !num.IsUint64() {
+@@ -238,7 +244,7 @@ func LowerReflect(mod llvm.Module) {
+ // It also cleans up the IR for testing.
+ for _, typ := range types {
+ initializer := typ.typecode.Initializer()
+- references := llvm.ConstExtractValue(initializer, []uint32{0})
++ references := state.builder.CreateExtractValue(initializer, 0, "")
+ typ.typecode.SetInitializer(llvm.ConstNull(initializer.Type()))
+ if strings.HasPrefix(typ.name, "reflect/types.type:struct:") {
+ // Structs have a 'references' field that is not a typecode but
+@@ -260,7 +266,7 @@ func (state *typeCodeAssignmentState) getTypeCodeNum(typecode
llvm.Value) *big.I
+ name := ""
+ if class == "named" {
+ name = value
+- typecode = llvm.ConstExtractValue(typecode.Initializer(), []uint32{0})
++ typecode = state.builder.CreateExtractValue(typecode.Initializer(), 0, "")
+ class, value = getClassAndValueFromTypeCode(typecode)
+ }
+ if class == "basic" {
+@@ -344,7 +350,7 @@ func (state *typeCodeAssignmentState) getNonBasicTypeCode(class
string, typecode
+ switch class {
+ case "chan", "pointer", "slice":
+ // Prefix-style type kinds. The upper bits contain the element type.
+- sub := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0})
++ sub := state.builder.CreateExtractValue(typecode.Initializer(), 0, "")
+ return state.getTypeCodeNum(sub)
+ case "array":
+ // An array is basically a pair of (typecode, length) stored in a
+@@ -416,7 +422,7 @@ func (state *typeCodeAssignmentState) getArrayTypeNum(typecode
llvm.Value) int {
+ return num
+ }
+
+- elemTypeCode := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0})
++ elemTypeCode := state.builder.CreateExtractValue(typecode.Initializer(), 0,
"")
+ elemTypeNum := state.getTypeCodeNum(elemTypeCode)
+ if elemTypeNum.BitLen() > state.uintptrLen || !elemTypeNum.IsUint64() {
+ // TODO: make this a regular error
+@@ -424,7 +430,7 @@ func (state *typeCodeAssignmentState) getArrayTypeNum(typecode
llvm.Value) int {
+ }
+
+ // The array side table is a sequence of {element type, array length}.
+- arrayLength := llvm.ConstExtractValue(typecode.Initializer(), []uint32{1}).ZExtValue()
++ arrayLength := state.builder.CreateExtractValue(typecode.Initializer(), 1,
"").ZExtValue()
+ buf := makeVarint(elemTypeNum.Uint64())
+ buf = append(buf, makeVarint(arrayLength)...)
+
+@@ -454,7 +460,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode
llvm.Value) int
+
+ // Get the fields this struct type contains.
+ // The struct number will be the start index of
+- structTypeGlobal := llvm.ConstExtractValue(typecode.Initializer(),
[]uint32{0}).Operand(0).Initializer()
++ structTypeGlobal := state.builder.CreateExtractValue(typecode.Initializer(), 0,
"").Operand(0).Initializer()
+ numFields := structTypeGlobal.Type().ArrayLength()
+
+ // The first data that is stored in the struct sidetable is the number of
+@@ -471,28 +477,28 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode
llvm.Value) int
+ // the sidetable bigger.
+ for i := 0; i < numFields; i++ {
+ // Collect some information about this field.
+- field := llvm.ConstExtractValue(structTypeGlobal, []uint32{uint32(i)})
++ field := state.builder.CreateExtractValue(structTypeGlobal, i, "")
+
+- nameGlobal := llvm.ConstExtractValue(field, []uint32{1})
++ nameGlobal := state.builder.CreateExtractValue(field, 1, "")
+ if nameGlobal == llvm.ConstPointerNull(nameGlobal.Type()) {
+ panic("compiler: no name for this struct field")
+ }
+- fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0))
++ fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0), state.builder)
+ fieldNameNumber := state.getStructNameNumber(fieldNameBytes)
+
+ // See whether this struct field has an associated tag, and if so,
+ // store that tag in the tags sidetable.
+- tagGlobal := llvm.ConstExtractValue(field, []uint32{2})
++ tagGlobal := state.builder.CreateExtractValue(field, 2, "")
+ hasTag := false
+ tagNumber := 0
+ if tagGlobal != llvm.ConstPointerNull(tagGlobal.Type()) {
+ hasTag = true
+- tagBytes := getGlobalBytes(tagGlobal.Operand(0))
++ tagBytes := getGlobalBytes(tagGlobal.Operand(0), state.builder)
+ tagNumber = state.getStructNameNumber(tagBytes)
+ }
+
+ // The 'embedded' or 'anonymous' flag for this field.
+- embedded := llvm.ConstExtractValue(field, []uint32{3}).ZExtValue() != 0
++ embedded := state.builder.CreateExtractValue(field, 3, "").ZExtValue() != 0
+
+ // The first byte in the struct types sidetable is a flags byte with
+ // two bits in it.
+@@ -510,7 +516,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode
llvm.Value) int
+
+ // Get the type number and add it to the buffer.
+ // All fields have a type, so include it directly here.
+- typeNum := state.getTypeCodeNum(llvm.ConstExtractValue(field, []uint32{0}))
++ typeNum := state.getTypeCodeNum(state.builder.CreateExtractValue(field, 0,
""))
+ if typeNum.BitLen() > state.uintptrLen || !typeNum.IsUint64() {
+ // TODO: make this a regular error
+ panic("struct field has a type code that is too big")
+diff --git a/transform/rtcalls.go b/transform/rtcalls.go
+index 2f17f815..d70bc626 100644
+--- a/transform/rtcalls.go
++++ b/transform/rtcalls.go
+@@ -149,7 +149,7 @@ func OptimizeReflectImplements(mod llvm.Module) {
+ interfaceType := interfaceTypeBitCast.Operand(0)
+ if strings.HasPrefix(interfaceType.Name(), "reflect/types.type:named:") {
+ // Get the underlying type.
+- interfaceType = llvm.ConstExtractValue(interfaceType.Initializer(), []uint32{0})
++ interfaceType = builder.CreateExtractValue(interfaceType.Initializer(), 0,
"")
+ }
+ if !strings.HasPrefix(interfaceType.Name(), "reflect/types.type:interface:")
{
+ // This is an error. The Type passed to Implements should be of
+@@ -161,7 +161,7 @@ func OptimizeReflectImplements(mod llvm.Module) {
+ // Interface is unknown at compile time. This can't be optimized.
+ continue
+ }
+- typeAssertFunction := llvm.ConstExtractValue(interfaceType.Initializer(),
[]uint32{4}).Operand(0)
++ typeAssertFunction := builder.CreateExtractValue(interfaceType.Initializer(), 4,
"").Operand(0)
+
+ // Replace Implements call with the type assert call.
+ builder.SetInsertPointBefore(call)
+--
+2.36.1
+
diff --git a/0013-interp-change-object.llvmType-to-the-initializer-typ.patch
b/0013-interp-change-object.llvmType-to-the-initializer-typ.patch
new file mode 100644
index 0000000..4ef130d
--- /dev/null
+++ b/0013-interp-change-object.llvmType-to-the-initializer-typ.patch
@@ -0,0 +1,79 @@
+From 1004deaafd70d4eb94196977c20a5b1a17cded81 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Thu, 22 Sep 2022 01:06:40 +0200
+Subject: [PATCH 13/18] interp: change object.llvmType to the initializer type
+
+Previously it was a pointer type, which won't work with opaque pointers.
+Instead, use the global initializer type instead.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ go.mod | 2 +-
+ go.sum | 4 ++--
+ interp/interpreter.go | 2 +-
+ interp/memory.go | 4 ++--
+ 4 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/go.mod b/go.mod
+index feb4e0d6..a50f1174 100644
+--- a/go.mod
++++ b/go.mod
+@@ -17,7 +17,7 @@ require (
+
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
+
golang.org/x/tools v0.1.11
+ gopkg.in/yaml.v2 v2.4.0
+-
tinygo.org/x/go-llvm v0.0.0-20220921144624-dabbe3f30634
++
tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec
+ )
+
+ require (
+diff --git a/go.sum b/go.sum
+index 907364f9..4af03408 100644
+--- a/go.sum
++++ b/go.sum
+@@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod
h1:Co6ibVJAznAaIkqp8
+ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+-tinygo.org/x/go-llvm v0.0.0-20220921144624-dabbe3f30634
h1:hihbmHkJjalV4kGshoCF03P/G4IjoXcNAbzLblXLa/M=
+-tinygo.org/x/go-llvm v0.0.0-20220921144624-dabbe3f30634/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
++tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec
h1:FYtAFrw/YQPc644uNN65dW50FrEuVNaPBf70x23ApY4=
++tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+diff --git a/interp/interpreter.go b/interp/interpreter.go
+index d029aa33..8c783a70 100644
+--- a/interp/interpreter.go
++++ b/interp/interpreter.go
+@@ -637,7 +637,7 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ // Create the new object.
+ size := operands[0].(literalValue).value.(uint64)
+ alloca := object{
+- llvmType: inst.llvmInst.Type(),
++ llvmType: inst.llvmInst.AllocatedType(),
+ globalName: r.pkgName + "$alloca",
+ buffer: newRawValue(uint32(size)),
+ size: uint32(size),
+diff --git a/interp/memory.go b/interp/memory.go
+index 583f9355..6a537bad 100644
+--- a/interp/memory.go
++++ b/interp/memory.go
+@@ -37,7 +37,7 @@ import (
+ // ability to roll back interpreting a function.
+ type object struct {
+ llvmGlobal llvm.Value
+- llvmType llvm.Type // must match llvmGlobal.Type() if both are set, may be unset
if llvmGlobal is set
++ llvmType llvm.Type // must match llvmGlobal.GlobalValueType() if both are set,
may be unset if llvmGlobal is set
+ llvmLayoutType llvm.Type // LLVM type based on runtime.alloc layout parameter, if
available
+ globalName string // name, if not yet created (not guaranteed to be the final
name)
+ buffer value // buffer with value as given by interp, nil if external
+@@ -594,7 +594,7 @@ func (v pointerValue) toLLVMValue(llvmType llvm.Type, mem
*memoryView) (llvm.Val
+ var globalType llvm.Type
+ if !obj.llvmType.IsNil() {
+ // The exact type is known.
+- globalType = obj.llvmType.ElementType()
++ globalType = obj.llvmType
+ } else { // !obj.llvmLayoutType.IsNil()
+ // The exact type isn't known, but the object layout is known.
+ globalType = obj.llvmLayoutType
+--
+2.36.1
+
diff --git a/0014-all-remove-pointer-ElementType-calls.patch
b/0014-all-remove-pointer-ElementType-calls.patch
new file mode 100644
index 0000000..36f0818
--- /dev/null
+++ b/0014-all-remove-pointer-ElementType-calls.patch
@@ -0,0 +1,586 @@
+From 0cdaa0f6db40e372db24d945b557d03b97ff92e9 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Thu, 22 Sep 2022 13:33:00 +0200
+Subject: [PATCH 14/18] all: remove pointer ElementType calls
+
+This is needed for opaque pointers, which are enabled by default in
+LLVM 15.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ builder/build.go | 4 +--
+ compiler/asserts.go | 4 +--
+ compiler/calls.go | 58 ++++++++++++++-------------------
+ compiler/compiler.go | 15 +++++----
+ compiler/func.go | 2 +-
+ compiler/interface.go | 4 +--
+ compiler/ircheck/check.go | 5 +--
+ compiler/symbol.go | 15 ++-------
+ interp/compiler.go | 21 ++++++++----
+ interp/interp.go | 10 +++---
+ interp/interpreter.go | 2 +-
+ interp/memory.go | 23 +++++++------
+ transform/allocs.go | 2 +-
+ transform/gc.go | 4 +--
+ transform/interface-lowering.go | 2 +-
+ transform/llvm.go | 2 +-
+ transform/wasm-abi.go | 2 +-
+ 17 files changed, 82 insertions(+), 93 deletions(-)
+
+diff --git a/builder/build.go b/builder/build.go
+index 7a7dd9ac..488ee823 100644
+--- a/builder/build.go
++++ b/builder/build.go
+@@ -418,7 +418,7 @@ func Build(pkgName, outpath string, config *compileopts.Config,
action func(Buil
+ return errors.New("global not found: " + globalName)
+ }
+ name := global.Name()
+- newGlobal := llvm.AddGlobal(mod, global.Type().ElementType(),
name+".tmp")
++ newGlobal := llvm.AddGlobal(mod, global.GlobalValueType(), name+".tmp")
+ global.ReplaceAllUsesWith(newGlobal)
+ global.EraseFromParentAsGlobal()
+ newGlobal.SetName(name)
+@@ -1134,7 +1134,7 @@ func setGlobalValues(mod llvm.Module, globals
map[string]map[string]string) erro
+
+ // A strin is a {ptr, len} pair. We need these types to build the
+ // initializer.
+- initializerType := global.Type().ElementType()
++ initializerType := global.GlobalValueType()
+ if initializerType.TypeKind() != llvm.StructTypeKind || initializerType.StructName()
== "" {
+ return fmt.Errorf("%s: not a string", globalName)
+ }
+diff --git a/compiler/asserts.go b/compiler/asserts.go
+index 2a5265e9..ba482494 100644
+--- a/compiler/asserts.go
++++ b/compiler/asserts.go
+@@ -91,7 +91,7 @@ func (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value,
arrayLen i
+
+ // createUnsafeSliceCheck inserts a runtime check used for unsafe.Slice. This
+ // function must panic if the ptr/len parameters are invalid.
+-func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, lenType *types.Basic) {
++func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, elementType llvm.Type,
lenType *types.Basic) {
+ // From the documentation of unsafe.Slice:
+ // > At run time, if len is negative, or if ptr is nil and len is not
+ // > zero, a run-time panic occurs.
+@@ -105,7 +105,7 @@ func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, lenType
*types.Bas
+
+ // Determine the maximum slice size, and therefore the maximum value of the
+ // len parameter.
+- maxSize := b.maxSliceSize(ptr.Type().ElementType())
++ maxSize := b.maxSliceSize(elementType)
+ maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false)
+
+ // Do the check. By using unsigned greater than for the length check, signed
+diff --git a/compiler/calls.go b/compiler/calls.go
+index b38d770f..b122f0c8 100644
+--- a/compiler/calls.go
++++ b/compiler/calls.go
+@@ -20,7 +20,7 @@ const maxFieldsPerParam = 3
+ type paramInfo struct {
+ llvmType llvm.Type
+ name string // name, possibly with suffixes for e.g. struct fields
+- flags paramFlags
++ elemSize uint64 // size of pointer element type, or 0 if this isn't a pointer
+ }
+
+ // paramFlags identifies parameter attributes for flags. Most importantly, it
+@@ -96,13 +96,7 @@ func (c *compilerContext) expandFormalParamType(t llvm.Type, name
string, goType
+ // failed to expand this parameter: too many fields
+ }
+ // TODO: split small arrays
+- return []paramInfo{
+- {
+- llvmType: t,
+- name: name,
+- flags: getTypeFlags(goType),
+- },
+- }
++ return []paramInfo{c.getParamInfo(t, name, goType)}
+ }
+
+ // expandFormalParamOffsets returns a list of offsets from the start of an
+@@ -152,7 +146,6 @@ func (b *builder) expandFormalParam(v llvm.Value) []llvm.Value {
+ // Try to flatten a struct type to a list of types. Returns a 1-element slice
+ // with the passed in type if this is not possible.
+ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
types.Type) []paramInfo {
+- typeFlags := getTypeFlags(goType)
+ switch t.TypeKind() {
+ case llvm.StructTypeKind:
+ var paramInfos []paramInfo
+@@ -183,40 +176,37 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name
string, goType
+ }
+ }
+ subInfos := c.flattenAggregateType(subfield, name+"."+suffix,
extractSubfield(goType, i))
+- for i := range subInfos {
+- subInfos[i].flags |= typeFlags
+- }
+ paramInfos = append(paramInfos, subInfos...)
+ }
+ return paramInfos
+ default:
+- return []paramInfo{
+- {
+- llvmType: t,
+- name: name,
+- flags: typeFlags,
+- },
+- }
++ return []paramInfo{c.getParamInfo(t, name, goType)}
+ }
+ }
+
+-// getTypeFlags returns the type flags for a given type. It will not recurse
+-// into sub-types (such as in structs).
+-func getTypeFlags(t types.Type) paramFlags {
+- if t == nil {
+- return 0
++// getParamInfo collects information about a parameter. For example, if this
++// parameter is pointer-like, it will also store the element type for the
++// dereferenceable_or_null attribute.
++func (c *compilerContext) getParamInfo(t llvm.Type, name string, goType types.Type)
paramInfo {
++ info := paramInfo{
++ llvmType: t,
++ name: name,
+ }
+- switch t.Underlying().(type) {
+- case *types.Pointer:
+- // Pointers in Go must either point to an object or be nil.
+- return paramIsDeferenceableOrNull
+- case *types.Chan, *types.Map:
+- // Channels and maps are implemented as pointers pointing to some
+- // object, and follow the same rules as *types.Pointer.
+- return paramIsDeferenceableOrNull
+- default:
+- return 0
++ if goType != nil {
++ switch underlying := goType.Underlying().(type) {
++ case *types.Pointer:
++ // Pointers in Go must either point to an object or be nil.
++ info.elemSize = c.targetData.TypeAllocSize(c.getLLVMType(underlying.Elem()))
++ case *types.Chan:
++ // Channels are implemented simply as a *runtime.channel.
++ info.elemSize =
c.targetData.TypeAllocSize(c.getLLVMRuntimeType("channel"))
++ case *types.Map:
++ // Maps are similar to channels: they are implemented as a
++ // *runtime.hashmap.
++ info.elemSize =
c.targetData.TypeAllocSize(c.getLLVMRuntimeType("hashmap"))
++ }
+ }
++ return info
+ }
+
+ // extractSubfield extracts a field from a struct, or returns null if this is
+diff --git a/compiler/compiler.go b/compiler/compiler.go
+index 3d29628c..fc47c29c 100644
+--- a/compiler/compiler.go
++++ b/compiler/compiler.go
+@@ -862,7 +862,7 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg
*ssa.Package
+ if files, ok := c.embedGlobals[member.Name()]; ok {
+ c.createEmbedGlobal(member, global, files)
+ } else if !info.extern {
+- global.SetInitializer(llvm.ConstNull(global.Type().ElementType()))
++ global.SetInitializer(llvm.ConstNull(global.GlobalValueType()))
+ global.SetVisibility(llvm.HiddenVisibility)
+ if info.section != "" {
+ global.SetSection(info.section)
+@@ -1405,7 +1405,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
+ b.CreateRet(b.getValue(instr.Results[0]))
+ } else {
+ // Multiple return values. Put them all in a struct.
+- retVal := llvm.ConstNull(b.llvmFn.Type().ElementType().ReturnType())
++ retVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType())
+ for i, result := range instr.Results {
+ val := b.getValue(result)
+ retVal = b.CreateInsertValue(retVal, val, i, "")
+@@ -1444,7 +1444,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues
[]llvm.Value, c
+ elemsBuf := b.CreateExtractValue(elems, 0, "append.elemsBuf")
+ elemsPtr := b.CreateBitCast(elemsBuf, b.i8ptrType, "append.srcPtr")
+ elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
+- elemType := srcBuf.Type().ElementType()
++ elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
+ elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
+ result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr,
srcLen, srcCap, elemsLen, elemSize}, "append.new")
+ newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
+@@ -1497,7 +1497,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues
[]llvm.Value, c
+ srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
+ dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray")
+ srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray")
+- elemType := dstBuf.Type().ElementType()
++ elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
+ dstBuf = b.CreateBitCast(dstBuf, b.i8ptrType, "copy.dstPtr")
+ srcBuf = b.CreateBitCast(srcBuf, b.i8ptrType, "copy.srcPtr")
+ elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
+@@ -1637,7 +1637,8 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues
[]llvm.Value, c
+ b.uintptrType,
+ b.uintptrType,
+ }, false))
+- b.createUnsafeSliceCheck(ptr, len, argTypes[1].Underlying().(*types.Basic))
++ elementType := b.getLLVMType(argTypes[0].Underlying().(*types.Pointer).Elem())
++ b.createUnsafeSliceCheck(ptr, len, elementType,
argTypes[1].Underlying().(*types.Basic))
+ if len.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
+ // Too small, zero-extend len.
+ len = b.CreateZExt(len, b.uintptrType, "")
+@@ -1712,7 +1713,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon)
(llvm.Value, error)
+ // Eventually we might be able to eliminate this special case
+ // entirely. For details, see:
+ //
https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-i...
+- calleeType = llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil,
false)
++ calleeType = llvm.FunctionType(callee.GlobalValueType().ReturnType(), nil, false)
+ callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType,
b.funcPtrAddrSpace))
+ }
+ case *ssa.MakeClosure:
+@@ -3095,7 +3096,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
+ }
+ case token.MUL: // *x, dereference pointer
+ valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem())
+- if b.targetData.TypeAllocSize(x.Type().ElementType()) == 0 {
++ if b.targetData.TypeAllocSize(valueType) == 0 {
+ // zero-length data
+ return llvm.ConstNull(valueType), nil
+ } else if strings.HasSuffix(unop.X.String(), "$funcaddr") {
+diff --git a/compiler/func.go b/compiler/func.go
+index c6a8802d..4203fdf7 100644
+--- a/compiler/func.go
++++ b/compiler/func.go
+@@ -73,7 +73,7 @@ func (c *compilerContext) getFuncType(typ *types.Signature) llvm.Type
{
+ return c.ctx.StructType([]llvm.Type{c.i8ptrType, c.rawVoidFuncType}, false)
+ }
+
+-// getRawFuncType returns a LLVM function pointer type for a given signature.
++// getRawFuncType returns a LLVM function type for a given signature.
+ func (c *compilerContext) getRawFuncType(typ *types.Signature) llvm.Type {
+ // Get the return type.
+ var returnType llvm.Type
+diff --git a/compiler/interface.go b/compiler/interface.go
+index 106c327a..2007b7d7 100644
+--- a/compiler/interface.go
++++ b/compiler/interface.go
+@@ -86,7 +86,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
+ if _, ok := typ.Underlying().(*types.Pointer); !ok {
+ ptrTo = c.getTypeCode(types.NewPointer(typ))
+ }
+- globalValue := llvm.ConstNull(global.Type().ElementType())
++ globalValue := llvm.ConstNull(global.GlobalValueType())
+ if !references.IsNil() {
+ globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "")
+ }
+@@ -533,7 +533,7 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function,
llvmFnType
+
+ receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0]
+ params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...)
+- if llvmFn.Type().ElementType().ReturnType().TypeKind() == llvm.VoidTypeKind {
++ if llvmFnType.ReturnType().TypeKind() == llvm.VoidTypeKind {
+ b.CreateCall(llvmFnType, llvmFn, params, "")
+ b.CreateRetVoid()
+ } else {
+diff --git a/compiler/ircheck/check.go b/compiler/ircheck/check.go
+index 30c6ee17..e2b7ed51 100644
+--- a/compiler/ircheck/check.go
++++ b/compiler/ircheck/check.go
+@@ -70,10 +70,7 @@ func (c *checker) checkType(t llvm.Type, checked
map[llvm.Type]struct{}, special
+ return fmt.Errorf("failed to verify element type of array type %s: %s",
t.String(), err.Error())
+ }
+ case llvm.PointerTypeKind:
+- // check underlying type
+- if err := c.checkType(t.ElementType(), checked, specials); err != nil {
+- return fmt.Errorf("failed to verify underlying type of pointer type %s:
%s", t.String(), err.Error())
+- }
++ // Pointers can't be checked in an opaque pointer world.
+ case llvm.VectorTypeKind:
+ // check element type
+ if err := c.checkType(t.ElementType(), checked, specials); err != nil {
+diff --git a/compiler/symbol.go b/compiler/symbol.go
+index 83fe050b..01b3fc37 100644
+--- a/compiler/symbol.go
++++ b/compiler/symbol.go
+@@ -83,7 +83,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type,
llvm.Value)
+ // Add an extra parameter as the function context. This context is used in
+ // closures and bound methods, but should be optimized away when not used.
+ if !info.exported {
+- paramInfos = append(paramInfos, paramInfo{llvmType: c.i8ptrType, name:
"context", flags: 0})
++ paramInfos = append(paramInfos, paramInfo{llvmType: c.i8ptrType, name:
"context", elemSize: 0})
+ }
+
+ var paramTypes []llvm.Type
+@@ -112,17 +112,8 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type,
llvm.Value)
+
+ dereferenceableOrNullKind := llvm.AttributeKindID("dereferenceable_or_null")
+ for i, info := range paramInfos {
+- if info.flags¶mIsDeferenceableOrNull == 0 {
+- continue
+- }
+- if info.llvmType.TypeKind() == llvm.PointerTypeKind {
+- el := info.llvmType.ElementType()
+- size := c.targetData.TypeAllocSize(el)
+- if size == 0 {
+- // dereferenceable_or_null(0) appears to be illegal in LLVM.
+- continue
+- }
+- dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, size)
++ if info.elemSize != 0 {
++ dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind,
info.elemSize)
+ llvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull)
+ }
+ }
+diff --git a/interp/compiler.go b/interp/compiler.go
+index 20723c64..ffef69e5 100644
+--- a/interp/compiler.go
++++ b/interp/compiler.go
+@@ -209,7 +209,7 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
+ case llvm.Alloca:
+ // Alloca allocates stack space for local variables.
+ numElements := r.getValue(inst.llvmInst.Operand(0)).(literalValue).value.(uint32)
+- elementSize := r.targetData.TypeAllocSize(inst.llvmInst.Type().ElementType())
++ elementSize := r.targetData.TypeAllocSize(inst.llvmInst.AllocatedType())
+ inst.operands = []value{
+ literalValue{elementSize * uint64(numElements)},
+ }
+@@ -218,17 +218,17 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
+ inst.name = llvmInst.Name()
+ ptr := llvmInst.Operand(0)
+ n := llvmInst.OperandsCount()
+- elementType := ptr.Type().ElementType()
++ elementType := llvmInst.GEPSourceElementType()
+ // gep: [source ptr, dest value size, pairs of indices...]
+ inst.operands = []value{
+ r.getValue(ptr),
+- literalValue{r.targetData.TypeAllocSize(llvmInst.Type().ElementType())},
+ r.getValue(llvmInst.Operand(1)),
+ literalValue{r.targetData.TypeAllocSize(elementType)},
+ }
+ for i := 2; i < n; i++ {
+ operand := r.getValue(llvmInst.Operand(i))
+- if elementType.TypeKind() == llvm.StructTypeKind {
++ switch elementType.TypeKind() {
++ case llvm.StructTypeKind:
+ index := operand.(literalValue).value.(uint32)
+ elementOffset := r.targetData.ElementOffset(elementType, int(index))
+ // Encode operands in a special way. The elementOffset
+@@ -242,12 +242,15 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
+ // runtime.
+ inst.operands = append(inst.operands, literalValue{elementOffset},
literalValue{^uint64(index)})
+ elementType = elementType.StructElementTypes()[index]
+- } else {
++ case llvm.ArrayTypeKind:
+ elementType = elementType.ElementType()
+ elementSize := r.targetData.TypeAllocSize(elementType)
+ elementSizeOperand := literalValue{elementSize}
+ // Add operand * elementSizeOperand bytes to the pointer.
+ inst.operands = append(inst.operands, operand, elementSizeOperand)
++ default:
++ // This should be unreachable.
++ panic("unknown type: " + elementType.String())
+ }
+ }
+ case llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt:
+@@ -267,10 +270,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
+ case llvm.StructTypeKind:
+ offset += r.targetData.ElementOffset(indexingType, int(index))
+ indexingType = indexingType.StructElementTypes()[index]
+- default: // ArrayTypeKind
++ case llvm.ArrayTypeKind:
+ indexingType = indexingType.ElementType()
+ elementSize := r.targetData.TypeAllocSize(indexingType)
+ offset += elementSize * uint64(index)
++ default:
++ panic("unknown type kind") // unreachable
+ }
+ }
+ size := r.targetData.TypeAllocSize(inst.llvmInst.Type())
+@@ -290,10 +295,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
+ case llvm.StructTypeKind:
+ offset += r.targetData.ElementOffset(indexingType, int(index))
+ indexingType = indexingType.StructElementTypes()[index]
+- default: // ArrayTypeKind
++ case llvm.ArrayTypeKind:
+ indexingType = indexingType.ElementType()
+ elementSize := r.targetData.TypeAllocSize(indexingType)
+ offset += elementSize * uint64(index)
++ default:
++ panic("unknown type kind") // unreachable
+ }
+ }
+ // insertvalue [agg, elt, byteOffset]
+diff --git a/interp/interp.go b/interp/interp.go
+index 856f08b1..7833dfe9 100644
+--- a/interp/interp.go
++++ b/interp/interp.go
+@@ -156,7 +156,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
+ if obj.constant {
+ continue // constant buffers can't have been modified
+ }
+- initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.Type().ElementType(),
&mem)
++ initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(),
&mem)
+ if err == errInvalidPtrToIntSize {
+ // This can happen when a previous interp run did not have the
+ // correct LLVM type for a global and made something up. In that
+@@ -190,7 +190,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
+ if err != nil {
+ return err
+ }
+- if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() {
++ if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {
+ panic("initializer type mismatch")
+ }
+ obj.llvmGlobal.SetInitializer(initializer)
+@@ -213,7 +213,7 @@ func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error
{
+ r.pkgName = initName[:len(initName)-len(".init")]
+
+ // Create new function with the interp result.
+- newFn := llvm.AddFunction(mod, fn.Name()+".tmp", fn.Type().ElementType())
++ newFn := llvm.AddFunction(mod, fn.Name()+".tmp", fn.GlobalValueType())
+ newFn.SetLinkage(fn.Linkage())
+ newFn.SetVisibility(fn.Visibility())
+ entry := mod.Context().AddBasicBlock(newFn, "entry")
+@@ -263,11 +263,11 @@ func RunFunc(fn llvm.Value, timeout time.Duration, debug bool)
error {
+ if obj.constant {
+ continue // constant, so can't have been modified
+ }
+- initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.Type().ElementType(),
&mem)
++ initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(),
&mem)
+ if err != nil {
+ return err
+ }
+- if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() {
++ if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {
+ panic("initializer type mismatch")
+ }
+ obj.llvmGlobal.SetInitializer(initializer)
+diff --git a/interp/interpreter.go b/interp/interpreter.go
+index 8c783a70..c438b4b6 100644
+--- a/interp/interpreter.go
++++ b/interp/interpreter.go
+@@ -655,7 +655,7 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ // GetElementPtr does pointer arithmetic, changing the offset of the
+ // pointer into the underlying object.
+ var offset uint64
+- for i := 2; i < len(operands); i += 2 {
++ for i := 1; i < len(operands); i += 2 {
+ index := operands[i].Uint()
+ elementSize := operands[i+1].Uint()
+ if int64(elementSize) < 0 {
+diff --git a/interp/memory.go b/interp/memory.go
+index 6a537bad..82ab716d 100644
+--- a/interp/memory.go
++++ b/interp/memory.go
+@@ -808,14 +808,17 @@ func (v rawValue) rawLLVMValue(mem *memoryView) (llvm.Value, error)
{
+ if err != nil {
+ return llvm.Value{}, err
+ }
+- elementType := field.Type().ElementType()
+- if elementType.TypeKind() == llvm.StructTypeKind {
+- // There are some special pointer types that should be used as a
+- // ptrtoint, so that they can be used in certain optimizations.
+- name := elementType.StructName()
+- if name == "runtime.typecodeID" || name ==
"runtime.funcValueWithSignature" {
+- uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8)
+- field = llvm.ConstPtrToInt(field, uintptrType)
++ if !field.IsAGlobalVariable().IsNil() {
++ elementType := field.GlobalValueType()
++ if elementType.TypeKind() == llvm.StructTypeKind {
++ // There are some special pointer types that should be used
++ // as a ptrtoint, so that they can be used in certain
++ // optimizations.
++ name := elementType.StructName()
++ if name == "runtime.typecodeID" || name ==
"runtime.funcValueWithSignature" {
++ uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8)
++ field = llvm.ConstPtrToInt(field, uintptrType)
++ }
+ }
+ }
+ structFields = append(structFields, field)
+@@ -998,7 +1001,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
+ ptr := llvmValue.Operand(0)
+ index := llvmValue.Operand(1)
+ numOperands := llvmValue.OperandsCount()
+- elementType := ptr.Type().ElementType()
++ elementType := llvmValue.GEPSourceElementType()
+ totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()
+ for i := 2; i < numOperands; i++ {
+ indexValue := llvmValue.Operand(i)
+@@ -1173,7 +1176,7 @@ func (r *runner) getValue(llvmValue llvm.Value) value {
+ r.globals[llvmValue] = index
+ r.objects = append(r.objects, obj)
+ if !llvmValue.IsAGlobalVariable().IsNil() {
+- obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.Type().ElementType()))
++ obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.GlobalValueType()))
+ if initializer := llvmValue.Initializer(); !initializer.IsNil() {
+ obj.buffer = r.getValue(initializer)
+ obj.constant = llvmValue.IsGlobalConstant()
+diff --git a/transform/allocs.go b/transform/allocs.go
+index af7c70b2..5be7df2d 100644
+--- a/transform/allocs.go
++++ b/transform/allocs.go
+@@ -124,7 +124,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp,
logger func(tok
+ alloca.SetAlignment(alignment)
+
+ // Zero the allocation inside the block where the value was originally allocated.
+- zero := llvm.ConstNull(alloca.Type().ElementType())
++ zero := llvm.ConstNull(alloca.AllocatedType())
+ builder.SetInsertPointBefore(bitcast)
+ store := builder.CreateStore(zero, alloca)
+ store.SetAlignment(alignment)
+diff --git a/transform/gc.go b/transform/gc.go
+index 514fb1bf..e2d23987 100644
+--- a/transform/gc.go
++++ b/transform/gc.go
+@@ -18,7 +18,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ stackChainStart := mod.NamedGlobal("runtime.stackChainStart")
+ if !stackChainStart.IsNil() {
+ stackChainStart.SetLinkage(llvm.InternalLinkage)
+- stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.Type().ElementType()))
++ stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.GlobalValueType()))
+ stackChainStart.SetGlobalConstant(true)
+ }
+ return false
+@@ -96,7 +96,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
+ return false
+ }
+ stackChainStart.SetLinkage(llvm.InternalLinkage)
+- stackChainStartType := stackChainStart.Type().ElementType()
++ stackChainStartType := stackChainStart.GlobalValueType()
+ stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))
+
+ // Iterate until runtime.trackPointer has no uses left.
+diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go
+index f28443dc..9e2ffa90 100644
+--- a/transform/interface-lowering.go
++++ b/transform/interface-lowering.go
+@@ -423,7 +423,7 @@ func (p *lowerInterfacesPass) defineInterfaceImplementsFunc(fn
llvm.Value, itf *
+ func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf
*interfaceInfo, signature *signatureInfo) {
+ context := fn.LastParam()
+ actualType := llvm.PrevParam(context)
+- returnType := fn.Type().ElementType().ReturnType()
++ returnType := fn.GlobalValueType().ReturnType()
+ context.SetName("context")
+ actualType.SetName("actualType")
+ fn.SetLinkage(llvm.InternalLinkage)
+diff --git a/transform/llvm.go b/transform/llvm.go
+index 17968f8a..7042b32d 100644
+--- a/transform/llvm.go
++++ b/transform/llvm.go
+@@ -66,7 +66,7 @@ func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {
+ // function used for creating reflection sidetables, for example.
+ func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value
{
+ oldGlobal := mod.NamedGlobal(name)
+- globalType, global := makeGlobalArray(mod, buf, name+".tmp",
oldGlobal.Type().ElementType())
++ globalType, global := makeGlobalArray(mod, buf, name+".tmp",
oldGlobal.GlobalValueType())
+ gep := llvm.ConstGEP(globalType, global, []llvm.Value{
+ llvm.ConstInt(mod.Context().Int32Type(), 0, false),
+ llvm.ConstInt(mod.Context().Int32Type(), 0, false),
+diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go
+index 064e38f4..83a16d85 100644
+--- a/transform/wasm-abi.go
++++ b/transform/wasm-abi.go
+@@ -50,7 +50,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config)
error {
+ paramTypes := []llvm.Type{}
+
+ // Check return type for 64-bit integer.
+- fnType := fn.Type().ElementType()
++ fnType := fn.GlobalValueType()
+ returnType := fnType.ReturnType()
+ if returnType == int64Type {
+ hasInt64 = true
+--
+2.36.1
+
diff --git a/0015-transform-fix-memory-corruption-issues.patch
b/0015-transform-fix-memory-corruption-issues.patch
new file mode 100644
index 0000000..d209b69
--- /dev/null
+++ b/0015-transform-fix-memory-corruption-issues.patch
@@ -0,0 +1,31 @@
+From 6bf7aa1623b6d7d9a269df876453af22b1c54c2d Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Wed, 12 Oct 2022 21:46:50 +0200
+Subject: [PATCH 15/18] transform: fix memory corruption issues
+
+There was a bug in the wasm ABI lowering pass (found using
+AddressSanitizer on LLVM 15) that resulted in a rather subtle memory
+corruption. This commit fixes this issues.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ transform/wasm-abi.go | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go
+index 83a16d85..08122a3e 100644
+--- a/transform/wasm-abi.go
++++ b/transform/wasm-abi.go
+@@ -88,8 +88,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config)
error {
+ // Update all users to call the external function.
+ // The old $i64wrapper function could be removed, but it may as well
+ // be left in place.
+- for use := fn.FirstUse(); !use.IsNil(); use = use.NextUse() {
+- call := use.User()
++ for _, call := range getUses(fn) {
+
entryBlockBuilder.SetInsertPointBefore(call.InstructionParent().Parent().EntryBasicBlock().FirstInstruction())
+ builder.SetInsertPointBefore(call)
+ callParams := []llvm.Value{}
+--
+2.36.1
+
diff --git a/0016-riscv-add-target-abi-metadata-flag.patch
b/0016-riscv-add-target-abi-metadata-flag.patch
new file mode 100644
index 0000000..e194223
--- /dev/null
+++ b/0016-riscv-add-target-abi-metadata-flag.patch
@@ -0,0 +1,193 @@
+From 003963ddc796960ce498361409a9d121366b1c42 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Wed, 12 Oct 2022 22:05:38 +0000
+Subject: [PATCH 16/18] riscv: add "target-abi" metadata flag
+
+This flag is necessary in LLVM 15 because it appears that LLVM 15 has
+changed the default target ABI from lp64 to lp64d. This results in a
+linker failure. Setting the "target-abi" forces the RISC-V backend to
+use the intended target ABI.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ builder/build.go | 1 +
+ builder/library.go | 7 +++++--
+ compileopts/config.go | 13 +++++++++++++
+ compileopts/target.go | 1 +
+ compiler/compiler.go | 13 +++++++++++++
+ compiler/compiler_test.go | 1 +
+ targets/riscv32.json | 4 ++--
+ targets/riscv64.json | 4 ++--
+ 8 files changed, 38 insertions(+), 6 deletions(-)
+
+diff --git a/builder/build.go b/builder/build.go
+index 488ee823..4818185f 100644
+--- a/builder/build.go
++++ b/builder/build.go
+@@ -170,6 +170,7 @@ func Build(pkgName, outpath string, config *compileopts.Config,
action func(Buil
+ Triple: config.Triple(),
+ CPU: config.CPU(),
+ Features: config.Features(),
++ ABI: config.ABI(),
+ GOOS: config.GOOS(),
+ GOARCH: config.GOARCH(),
+ CodeModel: config.CodeModel(),
+diff --git a/builder/library.go b/builder/library.go
+index 385f1610..87822d15 100644
+--- a/builder/library.go
++++ b/builder/library.go
+@@ -155,6 +155,9 @@ func (l *Library) load(config *compileopts.Config, tmpdir string)
(job *compileJ
+ args = append(args, "-mcpu="+cpu)
+ }
+ }
++ if config.ABI() != "" {
++ args = append(args, "-mabi="+config.ABI())
++ }
+ if strings.HasPrefix(target, "arm") || strings.HasPrefix(target,
"thumb") {
+ if strings.Split(target, "-")[2] == "linux" {
+ args = append(args, "-fno-unwind-tables",
"-fno-asynchronous-unwind-tables")
+@@ -170,10 +173,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string)
(job *compileJ
+ args = append(args, "-mdouble=64")
+ }
+ if strings.HasPrefix(target, "riscv32-") {
+- args = append(args, "-march=rv32imac", "-mabi=ilp32",
"-fforce-enable-int128")
++ args = append(args, "-march=rv32imac", "-fforce-enable-int128")
+ }
+ if strings.HasPrefix(target, "riscv64-") {
+- args = append(args, "-march=rv64gc", "-mabi=lp64")
++ args = append(args, "-march=rv64gc")
+ }
+ if strings.HasPrefix(target, "xtensa") {
+ // Hack to work around an issue in the Xtensa port:
+diff --git a/compileopts/config.go b/compileopts/config.go
+index cd49283d..80ea8cff 100644
+--- a/compileopts/config.go
++++ b/compileopts/config.go
+@@ -47,6 +47,12 @@ func (c *Config) Features() string {
+ return c.Target.Features + "," + c.Options.LLVMFeatures
+ }
+
++// ABI returns the -mabi= flag for this target (like -mabi=lp64). A zero-length
++// string is returned if the target doesn't specify an ABI.
++func (c *Config) ABI() string {
++ return c.Target.ABI
++}
++
+ // GOOS returns the GOOS of the target. This might not always be the actual OS:
+ // for example, bare-metal targets will usually pretend to be linux to get the
+ // standard library to compile.
+@@ -230,6 +236,9 @@ func (c *Config) LibcPath(name string) (path string, precompiled
bool) {
+ if c.CPU() != "" {
+ archname += "-" + c.CPU()
+ }
++ if c.ABI() != "" {
++ archname += "-" + c.ABI()
++ }
+
+ // Try to load a precompiled library.
+ precompiledDir := filepath.Join(goenv.Get("TINYGOROOT"), "pkg",
archname, name)
+@@ -335,6 +344,10 @@ func (c *Config) CFlags() []string {
+ cflags = append(cflags, "-mcpu="+c.Target.CPU)
+ }
+ }
++ // Set the -mabi flag, if needed.
++ if c.ABI() != "" {
++ cflags = append(cflags, "-mabi="+c.ABI())
++ }
+ return cflags
+ }
+
+diff --git a/compileopts/target.go b/compileopts/target.go
+index 865b8afe..c26c870e 100644
+--- a/compileopts/target.go
++++ b/compileopts/target.go
+@@ -26,6 +26,7 @@ type TargetSpec struct {
+ Inherits []string `json:"inherits"`
+ Triple string `json:"llvm-target"`
+ CPU string `json:"cpu"`
++ ABI string `json:"target-abi"` // rougly equivalent to -mabi=
flag
+ Features string `json:"features"`
+ GOOS string `json:"goos"`
+ GOARCH string `json:"goarch"`
+diff --git a/compiler/compiler.go b/compiler/compiler.go
+index fc47c29c..8b6e8661 100644
+--- a/compiler/compiler.go
++++ b/compiler/compiler.go
+@@ -41,6 +41,7 @@ type Config struct {
+ Triple string
+ CPU string
+ Features string
++ ABI string
+ GOOS string
+ GOARCH string
+ CodeModel string
+@@ -321,6 +322,18 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg
*ssa.Package,
+ c.dibuilder.Destroy()
+ }
+
++ // Add the "target-abi" flag, which is necessary on RISC-V otherwise it will
++ // pick one that doesn't match the -mabi Clang flag.
++ if c.ABI != "" {
++ c.mod.AddNamedMetadataOperand("llvm.module.flags",
++ c.ctx.MDNode([]llvm.Metadata{
++ llvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on
mismatch
++ c.ctx.MDString("target-abi"),
++ c.ctx.MDString(c.ABI),
++ }),
++ )
++ }
++
+ return c.mod, c.diagnostics
+ }
+
+diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go
+index 2ed26921..a5cd9c6b 100644
+--- a/compiler/compiler_test.go
++++ b/compiler/compiler_test.go
+@@ -73,6 +73,7 @@ func TestCompiler(t *testing.T) {
+ compilerConfig := &Config{
+ Triple: config.Triple(),
+ Features: config.Features(),
++ ABI: config.ABI(),
+ GOOS: config.GOOS(),
+ GOARCH: config.GOARCH(),
+ CodeModel: config.CodeModel(),
+diff --git a/targets/riscv32.json b/targets/riscv32.json
+index c3c8dff5..a2878089 100644
+--- a/targets/riscv32.json
++++ b/targets/riscv32.json
+@@ -1,12 +1,12 @@
+ {
+ "inherits": ["riscv"],
+ "llvm-target": "riscv32-unknown-none",
++ "target-abi": "ilp32",
+ "build-tags": ["tinygo.riscv32"],
+ "scheduler": "tasks",
+ "default-stack-size": 2048,
+ "cflags": [
+- "-march=rv32imac",
+- "-mabi=ilp32"
++ "-march=rv32imac"
+ ],
+ "ldflags": [
+ "-melf32lriscv"
+diff --git a/targets/riscv64.json b/targets/riscv64.json
+index c2378e97..fc45c91c 100644
+--- a/targets/riscv64.json
++++ b/targets/riscv64.json
+@@ -1,10 +1,10 @@
+ {
+ "inherits": ["riscv"],
+ "llvm-target": "riscv64-unknown-none",
++ "target-abi": "lp64",
+ "build-tags": ["tinygo.riscv64"],
+ "cflags": [
+- "-march=rv64gc",
+- "-mabi=lp64"
++ "-march=rv64gc"
+ ],
+ "ldflags": [
+ "-melf64lriscv"
+--
+2.36.1
+
diff --git a/0017-interp-add-support-for-constant-icmp-instructions.patch
b/0017-interp-add-support-for-constant-icmp-instructions.patch
new file mode 100644
index 0000000..500803c
--- /dev/null
+++ b/0017-interp-add-support-for-constant-icmp-instructions.patch
@@ -0,0 +1,195 @@
+From 76f42a3fac44ac6d07c53b10ddadb683ca019684 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Tue, 18 Oct 2022 23:16:36 +0000
+Subject: [PATCH 17/18] interp: add support for constant icmp instructions
+
+These instructions sometimes pop up in LLVM 15, but they never occured
+in LLVM 14. Implementing them is relatively straightforward: simply
+generalize the code that already exists for llvm.ICmp interpreting.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ interp/interpreter.go | 84 +++++++++++++++++---------------
+ interp/memory.go | 11 +++++
+ interp/testdata/consteval.ll | 15 ++++++
+ interp/testdata/consteval.out.ll | 1 +
+ 4 files changed, 73 insertions(+), 38 deletions(-)
+
+diff --git a/interp/interpreter.go b/interp/interpreter.go
+index c438b4b6..83fd2cd9 100644
+--- a/interp/interpreter.go
++++ b/interp/interpreter.go
+@@ -723,46 +723,9 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ locals[inst.localIndex] = newagg
+ case llvm.ICmp:
+ predicate := llvm.IntPredicate(operands[2].(literalValue).value.(uint8))
+- var result bool
+ lhs := operands[0]
+ rhs := operands[1]
+- switch predicate {
+- case llvm.IntEQ, llvm.IntNE:
+- lhsPointer, lhsErr := lhs.asPointer(r)
+- rhsPointer, rhsErr := rhs.asPointer(r)
+- if (lhsErr == nil) != (rhsErr == nil) {
+- // Fast path: only one is a pointer, so they can't be equal.
+- result = false
+- } else if lhsErr == nil {
+- // Both must be nil, so both are pointers.
+- // Compare them directly.
+- result = lhsPointer.equal(rhsPointer)
+- } else {
+- // Fall back to generic comparison.
+- result = lhs.asRawValue(r).equal(rhs.asRawValue(r))
+- }
+- if predicate == llvm.IntNE {
+- result = !result
+- }
+- case llvm.IntUGT:
+- result = lhs.Uint() > rhs.Uint()
+- case llvm.IntUGE:
+- result = lhs.Uint() >= rhs.Uint()
+- case llvm.IntULT:
+- result = lhs.Uint() < rhs.Uint()
+- case llvm.IntULE:
+- result = lhs.Uint() <= rhs.Uint()
+- case llvm.IntSGT:
+- result = lhs.Int() > rhs.Int()
+- case llvm.IntSGE:
+- result = lhs.Int() >= rhs.Int()
+- case llvm.IntSLT:
+- result = lhs.Int() < rhs.Int()
+- case llvm.IntSLE:
+- result = lhs.Int() <= rhs.Int()
+- default:
+- return nil, mem, r.errorAt(inst, errors.New("interp: unsupported icmp"))
+- }
++ result := r.interpretICmp(lhs, rhs, predicate)
+ if result {
+ locals[inst.localIndex] = literalValue{uint8(1)}
+ } else {
+@@ -948,6 +911,51 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ return nil, mem, r.errorAt(bb.instructions[len(bb.instructions)-1],
errors.New("interp: reached end of basic block without terminator"))
+ }
+
++// Interpret an icmp instruction. Doesn't have side effects, only returns the
++// output of the comparison.
++func (r *runner) interpretICmp(lhs, rhs value, predicate llvm.IntPredicate) bool {
++ switch predicate {
++ case llvm.IntEQ, llvm.IntNE:
++ var result bool
++ lhsPointer, lhsErr := lhs.asPointer(r)
++ rhsPointer, rhsErr := rhs.asPointer(r)
++ if (lhsErr == nil) != (rhsErr == nil) {
++ // Fast path: only one is a pointer, so they can't be equal.
++ result = false
++ } else if lhsErr == nil {
++ // Both must be nil, so both are pointers.
++ // Compare them directly.
++ result = lhsPointer.equal(rhsPointer)
++ } else {
++ // Fall back to generic comparison.
++ result = lhs.asRawValue(r).equal(rhs.asRawValue(r))
++ }
++ if predicate == llvm.IntNE {
++ result = !result
++ }
++ return result
++ case llvm.IntUGT:
++ return lhs.Uint() > rhs.Uint()
++ case llvm.IntUGE:
++ return lhs.Uint() >= rhs.Uint()
++ case llvm.IntULT:
++ return lhs.Uint() < rhs.Uint()
++ case llvm.IntULE:
++ return lhs.Uint() <= rhs.Uint()
++ case llvm.IntSGT:
++ return lhs.Int() > rhs.Int()
++ case llvm.IntSGE:
++ return lhs.Int() >= rhs.Int()
++ case llvm.IntSLT:
++ return lhs.Int() < rhs.Int()
++ case llvm.IntSLE:
++ return lhs.Int() <= rhs.Int()
++ default:
++ // _should_ be unreachable, until LLVM adds new icmp operands (unlikely)
++ panic("interp: unsupported icmp")
++ }
++}
++
+ func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, mem
*memoryView, indent string) *Error {
+ numOperands := inst.llvmInst.OperandsCount()
+ operands := make([]llvm.Value, numOperands)
+diff --git a/interp/memory.go b/interp/memory.go
+index 82ab716d..248825f6 100644
+--- a/interp/memory.go
++++ b/interp/memory.go
+@@ -1031,6 +1031,17 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
+ for i := uint32(0); i < ptrSize; i++ {
+ v.buf[i] = ptrValue.pointer
+ }
++ case llvm.ICmp:
++ size := r.targetData.TypeAllocSize(llvmValue.Operand(0).Type())
++ lhs := newRawValue(uint32(size))
++ rhs := newRawValue(uint32(size))
++ lhs.set(llvmValue.Operand(0), r)
++ rhs.set(llvmValue.Operand(1), r)
++ if r.interpretICmp(lhs, rhs, llvmValue.IntPredicate()) {
++ v.buf[0] = 1 // result is true
++ } else {
++ v.buf[0] = 0 // result is false
++ }
+ default:
+ llvmValue.Dump()
+ println()
+diff --git a/interp/testdata/consteval.ll b/interp/testdata/consteval.ll
+index 9afb9ff7..d0c0e3b6 100644
+--- a/interp/testdata/consteval.ll
++++ b/interp/testdata/consteval.ll
+@@ -3,6 +3,7 @@ target triple = "x86_64--linux"
+
+ @intToPtrResult = global i8 0
+ @ptrToIntResult = global i8 0
++@icmpResult = global i8 0
+ @someArray = internal global {i16, i8, i8} zeroinitializer
+ @someArrayPointer = global i8* zeroinitializer
+
+@@ -15,6 +16,7 @@ define internal void @main.init() {
+ call void @testIntToPtr()
+ call void @testPtrToInt()
+ call void @testConstGEP()
++ call void @testICmp()
+ ret void
+ }
+
+@@ -48,3 +50,16 @@ define internal void @testConstGEP() {
+ store i8* getelementptr inbounds (i8, i8* bitcast ({i16, i8, i8}* @someArray to i8*),
i32 2), i8** @someArrayPointer
+ ret void
+ }
++
++define internal void @testICmp() {
++ br i1 icmp eq (i64 ptrtoint (i8* @ptrToIntResult to i64), i64 0), label %equal, label
%unequal
++equal:
++ ; should not be reached
++ store i8 1, i8* @icmpResult
++ ret void
++unequal:
++ ; should be reached
++ store i8 2, i8* @icmpResult
++ ret void
++ ret void
++}
+diff --git a/interp/testdata/consteval.out.ll b/interp/testdata/consteval.out.ll
+index 5fac449e..08d74c85 100644
+--- a/interp/testdata/consteval.out.ll
++++ b/interp/testdata/consteval.out.ll
+@@ -3,6 +3,7 @@ target triple = "x86_64--linux"
+
+ @intToPtrResult = local_unnamed_addr global i8 2
+ @ptrToIntResult = local_unnamed_addr global i8 2
++@icmpResult = local_unnamed_addr global i8 2
+ @someArray = internal global { i16, i8, i8 } zeroinitializer
+ @someArrayPointer = local_unnamed_addr global i8* getelementptr inbounds ({ i16, i8, i8
}, { i16, i8, i8 }* @someArray, i64 0, i32 1)
+
+--
+2.36.1
+
diff --git a/0018-ci-add-support-for-LLVM-15.patch
b/0018-ci-add-support-for-LLVM-15.patch
new file mode 100644
index 0000000..7c17787
--- /dev/null
+++ b/0018-ci-add-support-for-LLVM-15.patch
@@ -0,0 +1,3490 @@
+From 6557b534a1c2195cb7f2a465f8dc36662525f764 Mon Sep 17 00:00:00 2001
+From: Ayke van Laethem <aykevanlaethem(a)gmail.com>
+Date: Thu, 22 Sep 2022 13:39:51 +0200
+Subject: [PATCH 18/18] ci: add support for LLVM 15
+
+This commit switches to LLVM 15 everywhere by default, while still
+keeping LLVM 14 support.
+
+Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
+---
+ .github/workflows/build-macos.yml | 6 +-
+ .github/workflows/linux.yml | 16 +-
+ .github/workflows/windows.yml | 4 +-
+ Makefile | 6 +-
+ builder/cc1as.cpp | 21 +-
+ builder/cc1as.h | 7 +
+ builder/musl.go | 10 +-
+ cgo/libclang_config_llvm14.go | 4 +-
+ cgo/libclang_config_llvm15.go | 16 ++
+ compiler/func.go | 15 +-
+ compiler/intrinsics.go | 11 +-
+ compiler/llvmutil/llvm.go | 33 ++-
+ compiler/symbol.go | 11 +-
+ compiler/testdata/basic.go | 12 +-
+ compiler/testdata/basic.ll | 69 +++--
+ compiler/testdata/channel.ll | 110 +++-----
+ compiler/testdata/defer-cortex-m-qemu.ll | 267 +++++++++---------
+ compiler/testdata/float.ll | 22 +-
+ compiler/testdata/func.ll | 23 +-
+ compiler/testdata/gc.ll | 176 ++++++------
+ .../testdata/goroutine-cortex-m-qemu-tasks.ll | 189 ++++++-------
+ compiler/testdata/goroutine-wasm-asyncify.ll | 206 ++++++--------
+ compiler/testdata/interface.ll | 83 +++---
+ compiler/testdata/pointer.ll | 68 +++--
+ compiler/testdata/pragma.ll | 18 +-
+ compiler/testdata/slice.ll | 264 ++++++++---------
+ compiler/testdata/string.ll | 50 ++--
+ go.mod | 2 +-
+ go.sum | 4 +-
+ interp/interpreter.go | 16 +-
+ src/runtime/runtime.go | 6 +-
+ targets/esp32c3.json | 2 +-
+ targets/fe310.json | 2 +-
+ targets/k210.json | 2 +-
+ targets/riscv-qemu.json | 2 +-
+ transform/interface-lowering.go | 4 +-
+ transform/interrupt.go | 3 +-
+ transform/llvm.go | 6 +
+ transform/reflect.go | 11 +-
+ transform/rtcalls.go | 5 +-
+ 40 files changed, 898 insertions(+), 884 deletions(-)
+ create mode 100644 cgo/libclang_config_llvm15.go
+
+diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml
+index 2059574a..9197ea3c 100644
+--- a/.github/workflows/build-macos.yml
++++ b/.github/workflows/build-macos.yml
+@@ -40,7 +40,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-source
+ with:
+- key: llvm-source-14-macos-v1
++ key: llvm-source-15-macos-v1
+ path: |
+ llvm-project/clang/lib/Headers
+ llvm-project/clang/include
+@@ -54,7 +54,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-build
+ with:
+- key: llvm-build-14-macos-v1
++ key: llvm-build-15-macos-v1
+ path: llvm-build
+ - name: Build LLVM
+ if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+@@ -108,7 +108,7 @@ jobs:
+ - name: Install LLVM
+ shell: bash
+ run: |
+- HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14
++ HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@15
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Install Go
+diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
+index 8fc52717..cf26a4f2 100644
+--- a/.github/workflows/linux.yml
++++ b/.github/workflows/linux.yml
+@@ -43,7 +43,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-source
+ with:
+- key: llvm-source-14-linux-alpine-v1
++ key: llvm-source-15-linux-alpine-v1
+ path: |
+ llvm-project/clang/lib/Headers
+ llvm-project/clang/include
+@@ -57,7 +57,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-build
+ with:
+- key: llvm-build-14-linux-alpine-v1
++ key: llvm-build-15-linux-alpine-v1
+ path: llvm-build
+ - name: Build LLVM
+ if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+@@ -185,7 +185,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-source
+ with:
+- key: llvm-source-14-linux-asserts-v2
++ key: llvm-source-15-linux-asserts-v1
+ path: |
+ llvm-project/clang/lib/Headers
+ llvm-project/clang/include
+@@ -199,7 +199,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-build
+ with:
+- key: llvm-build-14-linux-asserts-v1
++ key: llvm-build-15-linux-asserts-v1
+ path: llvm-build
+ - name: Build LLVM
+ if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+@@ -277,7 +277,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-source
+ with:
+- key: llvm-source-14-linux-v2
++ key: llvm-source-15-linux-v1
+ path: |
+ llvm-project/clang/lib/Headers
+ llvm-project/clang/include
+@@ -291,7 +291,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-build
+ with:
+- key: llvm-build-14-linux-arm-v1
++ key: llvm-build-15-linux-arm-v1
+ path: llvm-build
+ - name: Build LLVM
+ if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+@@ -377,7 +377,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-source
+ with:
+- key: llvm-source-14-linux-v1
++ key: llvm-source-15-linux-v1
+ path: |
+ llvm-project/clang/lib/Headers
+ llvm-project/clang/include
+@@ -391,7 +391,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-build
+ with:
+- key: llvm-build-14-linux-arm64-v1
++ key: llvm-build-15-linux-arm64-v1
+ path: llvm-build
+ - name: Build LLVM
+ if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
+index 76c010cf..2ea1dc8c 100644
+--- a/.github/workflows/windows.yml
++++ b/.github/workflows/windows.yml
+@@ -35,7 +35,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-source
+ with:
+- key: llvm-source-14-windows-v2
++ key: llvm-source-15-windows-v1
+ path: |
+ llvm-project/clang/lib/Headers
+ llvm-project/clang/include
+@@ -49,7 +49,7 @@ jobs:
+ uses: actions/cache@v3
+ id: cache-llvm-build
+ with:
+- key: llvm-build-14-windows-v2
++ key: llvm-build-15-windows-v1
+ path: llvm-build
+ - name: Build LLVM
+ if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+diff --git a/Makefile b/Makefile
+index 1ef11d29..89927961 100644
+--- a/Makefile
++++ b/Makefile
+@@ -107,7 +107,7 @@ endif
+
+ .PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf
gen-device-nxp gen-device-avr gen-device-rp
+
+-LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen
core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendopenmp
instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option
profiledata scalaropts support target windowsmanifest
++LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen
core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendopenmp
instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option
profiledata scalaropts support target windowsdriver windowsmanifest
+
+ ifeq ($(OS),Windows_NT)
+ EXE = .exe
+@@ -142,7 +142,7 @@ else
+ endif
+
+ # Libraries that should be linked in for the statically linked Clang.
+-CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGen
clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangFormat clangFrontend
clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse
clangRewrite clangRewriteFrontend clangSema clangSerialization clangTooling
clangToolingASTDiff clangToolingCore clangToolingInclusions
++CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGen
clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangExtractAPI clangFormat
clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex
clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangSupport
clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions
+ CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
+
+ # Libraries that should be linked in for the statically linked LLD.
+@@ -230,7 +230,7 @@ gen-device-rp: build/gen-device-svd
+
+ # Get LLVM sources.
+ $(LLVM_PROJECTDIR)/llvm:
+- git clone -b xtensa_release_14.0.0-patched --depth=1
https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
++ git clone -b xtensa_release_15.x --depth=1
https://github.com/espressif/llvm-project
$(LLVM_PROJECTDIR)
+ llvm-source: $(LLVM_PROJECTDIR)/llvm
+
+ # Configure LLVM.
+diff --git a/builder/cc1as.cpp b/builder/cc1as.cpp
+index 11500121..cd3229ad 100644
+--- a/builder/cc1as.cpp
++++ b/builder/cc1as.cpp
+@@ -101,6 +101,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation
&Opts,
+
+ // Target Options
+ Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
++ if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))
++ Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());
++
+ Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
+ Opts.Features = Args.getAllArgValues(OPT_target_feature);
+
+@@ -203,6 +206,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation
&Opts,
+ .Default(0);
+ }
+
++ if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {
++ Opts.EmitDwarfUnwind =
++ llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())
++ .Case("always", EmitDwarfUnwindType::Always)
++ .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)
++ .Case("default", EmitDwarfUnwindType::Default);
++ }
++
+ return Success;
+ }
+
+@@ -253,6 +264,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
+ assert(MRI && "Unable to create target register info!");
+
+ MCTargetOptions MCOptions;
++ MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
++
+ std::unique_ptr<MCAsmInfo> MAI(
+ TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
+ assert(MAI && "Unable to create target asm info!");
+@@ -299,6 +312,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
+ // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
+ std::unique_ptr<MCObjectFileInfo> MOFI(
+ TheTarget->createMCObjectFileInfo(Ctx, PIC));
++ if (Opts.DarwinTargetVariantTriple)
++ MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
+ Ctx.setObjectFileInfo(MOFI.get());
+
+ if (Opts.SaveTemporaryLabels)
+@@ -347,7 +362,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
+
+ std::unique_ptr<MCCodeEmitter> CE;
+ if (Opts.ShowEncoding)
+- CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
++ CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+
+@@ -367,7 +382,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
+ }
+
+ std::unique_ptr<MCCodeEmitter> CE(
+- TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
++ TheTarget->createMCCodeEmitter(*MCII, Ctx));
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+ assert(MAB && "Unable to create asm backend!");
+@@ -389,7 +404,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
+ if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {
+ MCSection *AsmLabel = Ctx.getMachOSection(
+ "__LLVM", "__asm", MachO::S_REGULAR, 4,
SectionKind::getReadOnly());
+- Str.get()->SwitchSection(AsmLabel);
++ Str.get()->switchSection(AsmLabel);
+ Str.get()->emitZeros(1);
+ }
+
+diff --git a/builder/cc1as.h b/builder/cc1as.h
+index 538e9a26..150d6f14 100644
+--- a/builder/cc1as.h
++++ b/builder/cc1as.h
+@@ -85,6 +85,9 @@ struct AssemblerInvocation {
+ unsigned IncrementalLinkerCompatible : 1;
+ unsigned EmbedBitcode : 1;
+
++ /// Whether to emit DWARF unwind info.
++ EmitDwarfUnwindType EmitDwarfUnwind;
++
+ /// The name of the relocation model to use.
+ std::string RelocationModel;
+
+@@ -92,6 +95,9 @@ struct AssemblerInvocation {
+ /// otherwise.
+ std::string TargetABI;
+
++ /// Darwin target variant triple, the variant of the deployment target
++ /// for which the code is being compiled.
++ llvm::Optional<llvm::Triple> DarwinTargetVariantTriple;
+ /// @}
+
+ public:
+@@ -112,6 +118,7 @@ public:
+ Dwarf64 = 0;
+ DwarfVersion = 0;
+ EmbedBitcode = 0;
++ EmitDwarfUnwind = EmitDwarfUnwindType::Default;
+ }
+
+ static bool CreateFromArgs(AssemblerInvocation &Res,
+diff --git a/builder/musl.go b/builder/musl.go
+index a1967e37..c266898d 100644
+--- a/builder/musl.go
++++ b/builder/musl.go
+@@ -6,10 +6,12 @@ import (
+ "os"
+ "path/filepath"
+ "regexp"
++ "strconv"
+ "strings"
+
+ "github.com/tinygo-org/tinygo/compileopts"
+ "github.com/tinygo-org/tinygo/goenv"
++ "tinygo.org/x/go-llvm"
+ )
+
+ var Musl = Library{
+@@ -77,7 +79,7 @@ var Musl = Library{
+ cflags: func(target, headerPath string) []string {
+ arch := compileopts.MuslArchitecture(target)
+ muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl")
+- return []string{
++ cflags := []string{
+ "-std=c99", // same as in musl
+ "-D_XOPEN_SOURCE=700", // same as in musl
+ // Musl triggers some warnings and we don't want to show any
+@@ -103,6 +105,12 @@ var Musl = Library{
+ "-I" + muslDir + "/include",
+ "-fno-stack-protector",
+ }
++ llvmMajor, _ := strconv.Atoi(strings.SplitN(llvm.Version, ".", 2)[0])
++ if llvmMajor >= 15 {
++ // This flag was added in Clang 15. It is not present in LLVM 14.
++ cflags = append(cflags, "-Wno-deprecated-non-prototype")
++ }
++ return cflags
+ },
+ sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"),
"lib/musl/src") },
+ librarySources: func(target string) []string {
+diff --git a/cgo/libclang_config_llvm14.go b/cgo/libclang_config_llvm14.go
+index 0553bd50..953ce8e2 100644
+--- a/cgo/libclang_config_llvm14.go
++++ b/cgo/libclang_config_llvm14.go
+@@ -1,5 +1,5 @@
+-//go:build !byollvm
+-// +build !byollvm
++//go:build !byollvm && llvm14
++// +build !byollvm,llvm14
+
+ package cgo
+
+diff --git a/cgo/libclang_config_llvm15.go b/cgo/libclang_config_llvm15.go
+new file mode 100644
+index 00000000..e918a473
+--- /dev/null
++++ b/cgo/libclang_config_llvm15.go
+@@ -0,0 +1,16 @@
++//go:build !byollvm && !llvm14
++// +build !byollvm,!llvm14
++
++package cgo
++
++/*
++#cgo linux CFLAGS: -I/usr/lib/llvm-15/include
++#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@15/include
++#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@15/include
++#cgo freebsd CFLAGS: -I/usr/local/llvm15/include
++#cgo linux LDFLAGS: -L/usr/lib/llvm-15/lib -lclang
++#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@15/lib -lclang -lffi
++#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@15/lib -lclang -lffi
++#cgo freebsd LDFLAGS: -L/usr/local/llvm15/lib -lclang
++*/
++import "C"
+diff --git a/compiler/func.go b/compiler/func.go
+index 4203fdf7..404c7316 100644
+--- a/compiler/func.go
++++ b/compiler/func.go
+@@ -57,14 +57,15 @@ func (b *builder) extractFuncContext(funcValue llvm.Value) llvm.Value
{
+ // value. This may be an expensive operation.
+ func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcType
llvm.Type, funcPtr, context llvm.Value) {
+ context = b.CreateExtractValue(funcValue, 0, "")
+- bitcast := b.CreateExtractValue(funcValue, 1, "")
+- if !bitcast.IsAConstantExpr().IsNil() && bitcast.Opcode() == llvm.BitCast {
+- funcPtr = bitcast.Operand(0)
+- return
++ funcPtr = b.CreateExtractValue(funcValue, 1, "")
++ if !funcPtr.IsAConstantExpr().IsNil() && funcPtr.Opcode() == llvm.BitCast {
++ funcPtr = funcPtr.Operand(0) // needed for LLVM 14 (no opaque pointers)
++ }
++ if sig != nil {
++ funcType = b.getRawFuncType(sig)
++ llvmSig := llvm.PointerType(funcType, b.funcPtrAddrSpace)
++ funcPtr = b.CreateBitCast(funcPtr, llvmSig, "")
+ }
+- funcType = b.getRawFuncType(sig)
+- llvmSig := llvm.PointerType(funcType, b.funcPtrAddrSpace)
+- funcPtr = b.CreateBitCast(bitcast, llvmSig, "")
+ return
+ }
+
+diff --git a/compiler/intrinsics.go b/compiler/intrinsics.go
+index 9fedfbd6..a511e518 100644
+--- a/compiler/intrinsics.go
++++ b/compiler/intrinsics.go
+@@ -7,6 +7,7 @@ import (
+ "strconv"
+ "strings"
+
++ "github.com/tinygo-org/tinygo/compiler/llvmutil"
+ "tinygo.org/x/go-llvm"
+ )
+
+@@ -44,7 +45,10 @@ func (b *builder) defineIntrinsicFunction() {
+ // and will otherwise be lowered to regular libc memcpy/memmove calls.
+ func (b *builder) createMemoryCopyImpl() {
+ b.createFunctionStart(true)
+- fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" +
strconv.Itoa(b.uintptrType.IntTypeWidth())
++ fnName := "llvm." + b.fn.Name() + ".p0.p0.i" +
strconv.Itoa(b.uintptrType.IntTypeWidth())
++ if llvmutil.Major() < 15 { // compatibility with LLVM 14
++ fnName = "llvm." + b.fn.Name() + ".p0i8.p0i8.i" +
strconv.Itoa(b.uintptrType.IntTypeWidth())
++ }
+ llvmFn := b.mod.NamedFunction(fnName)
+ if llvmFn.IsNil() {
+ fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType, b.i8ptrType,
b.uintptrType, b.ctx.Int1Type()}, false)
+@@ -64,7 +68,10 @@ func (b *builder) createMemoryCopyImpl() {
+ // regular libc memset calls if they aren't optimized out in a different way.
+ func (b *builder) createMemoryZeroImpl() {
+ b.createFunctionStart(true)
+- fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
++ fnName := "llvm.memset.p0.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
++ if llvmutil.Major() < 15 { // compatibility with LLVM 14
++ fnName = "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
++ }
+ llvmFn := b.mod.NamedFunction(fnName)
+ if llvmFn.IsNil() {
+ fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.i8ptrType,
b.ctx.Int8Type(), b.uintptrType, b.ctx.Int1Type()}, false)
+diff --git a/compiler/llvmutil/llvm.go b/compiler/llvmutil/llvm.go
+index e73b68da..ca277765 100644
+--- a/compiler/llvmutil/llvm.go
++++ b/compiler/llvmutil/llvm.go
+@@ -7,7 +7,22 @@
+ // places would be a big risk if only one of them is updated.
+ package llvmutil
+
+-import "tinygo.org/x/go-llvm"
++import (
++ "strconv"
++ "strings"
++
++ "tinygo.org/x/go-llvm"
++)
++
++// Major returns the LLVM major version.
++func Major() int {
++ llvmMajor, err := strconv.Atoi(strings.SplitN(llvm.Version, ".", 2)[0])
++ if err != nil {
++ // sanity check, should be unreachable
++ panic("could not parse LLVM version: " + err.Error())
++ }
++ return llvmMajor
++}
+
+ // CreateEntryBlockAlloca creates a new alloca in the entry block, even though
+ // the IR builder is located elsewhere. It assumes that the insert point is
+@@ -78,12 +93,16 @@ func EmitLifetimeEnd(builder llvm.Builder, mod llvm.Module, ptr, size
llvm.Value
+ // getLifetimeStartFunc returns the llvm.lifetime.start intrinsic and creates it
+ // first if it doesn't exist yet.
+ func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
+- fn := mod.NamedFunction("llvm.lifetime.start.p0i8")
++ fnName := "llvm.lifetime.start.p0"
++ if Major() < 15 { // compatibility with LLVM 14
++ fnName = "llvm.lifetime.start.p0i8"
++ }
++ fn := mod.NamedFunction(fnName)
+ ctx := mod.Context()
+ i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
+ fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType},
false)
+ if fn.IsNil() {
+- fn = llvm.AddFunction(mod, "llvm.lifetime.start.p0i8", fnType)
++ fn = llvm.AddFunction(mod, fnName, fnType)
+ }
+ return fnType, fn
+ }
+@@ -91,12 +110,16 @@ func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value)
{
+ // getLifetimeEndFunc returns the llvm.lifetime.end intrinsic and creates it
+ // first if it doesn't exist yet.
+ func getLifetimeEndFunc(mod llvm.Module) (llvm.Type, llvm.Value) {
+- fn := mod.NamedFunction("llvm.lifetime.end.p0i8")
++ fnName := "llvm.lifetime.end.p0"
++ if Major() < 15 {
++ fnName = "llvm.lifetime.end.p0i8"
++ }
++ fn := mod.NamedFunction(fnName)
+ ctx := mod.Context()
+ i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
+ fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType},
false)
+ if fn.IsNil() {
+- fn = llvm.AddFunction(mod, "llvm.lifetime.end.p0i8", fnType)
++ fn = llvm.AddFunction(mod, fnName, fnType)
+ }
+ return fnType, fn
+ }
+diff --git a/compiler/symbol.go b/compiler/symbol.go
+index 01b3fc37..61ca4473 100644
+--- a/compiler/symbol.go
++++ b/compiler/symbol.go
+@@ -10,6 +10,7 @@ import (
+ "strconv"
+ "strings"
+
++ "github.com/tinygo-org/tinygo/compiler/llvmutil"
+ "github.com/tinygo-org/tinygo/loader"
+ "golang.org/x/tools/go/ssa"
+ "tinygo.org/x/go-llvm"
+@@ -353,7 +354,15 @@ func (c *compilerContext) addStandardDefinedAttributes(llvmFn
llvm.Value) {
+
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"),
0))
+ if strings.Split(c.Triple, "-")[0] == "x86_64" {
+ // Required by the ABI.
+- llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("uwtable"),
0))
++ if llvmutil.Major() < 15 {
++ // Needed for LLVM 14 support.
++ llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("uwtable"),
0))
++ } else {
++ // The uwtable has two possible values: sync (1) or async (2). We
++ // use sync because we currently don't use async unwind tables.
++ // For details, see:
https://llvm.org/docs/LangRef.html#function-attributes
++ llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("uwtable"),
1))
++ }
+ }
+ }
+
+diff --git a/compiler/testdata/basic.go b/compiler/testdata/basic.go
+index e9fcbad3..d2b4a96d 100644
+--- a/compiler/testdata/basic.go
++++ b/compiler/testdata/basic.go
+@@ -75,14 +75,18 @@ func complexMul(x, y complex64) complex64 {
+ // A type 'kv' also exists in function foo. Test that these two types don't
+ // conflict with each other.
+ type kv struct {
+- v float32
++ v float32
++ x, y, z int
+ }
+
+-func foo(a *kv) {
++var kvGlobal kv
++
++func foo() {
+ // Define a new 'kv' type.
+ type kv struct {
+- v byte
++ v byte
++ x, y, z int
+ }
+ // Use this type.
+- func(b *kv) {}(nil)
++ func(b kv) {}(kv{})
+ }
+diff --git a/compiler/testdata/basic.ll b/compiler/testdata/basic.ll
+index 4d88f66f..6ef0dc92 100644
+--- a/compiler/testdata/basic.ll
++++ b/compiler/testdata/basic.ll
+@@ -3,35 +3,37 @@ source_filename = "basic.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-%main.kv = type { float }
+-%main.kv.0 = type { i8 }
++%main.kv = type { float, i32, i32, i32 }
++%main.kv.0 = type { i8, i32, i32, i32 }
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++(a)main.kvGlobal = hidden global %main.kv zeroinitializer, align 4
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
++
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.addInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.addInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = add i32 %x, %y
+ ret i32 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.equalInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.equalInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp eq i32 %x, %y
+ ret i1 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.divInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.divInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp eq i32 %y, 0
+ br i1 %0, label %divbyzero.throw, label %divbyzero.next
+@@ -45,14 +47,14 @@ divbyzero.next: ; preds = %entry
+ ret i32 %5
+
+ divbyzero.throw: ; preds = %entry
+- call void @runtime.divideByZeroPanic(i8* undef) #2
++ call void @runtime.divideByZeroPanic(ptr undef) #2
+ unreachable
+ }
+
+-declare void @runtime.divideByZeroPanic(i8*) #0
++declare void @runtime.divideByZeroPanic(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.divUint(i32 %x, i32 %y, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.divUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp eq i32 %y, 0
+ br i1 %0, label %divbyzero.throw, label %divbyzero.next
+@@ -62,12 +64,12 @@ divbyzero.next: ; preds = %entry
+ ret i32 %1
+
+ divbyzero.throw: ; preds = %entry
+- call void @runtime.divideByZeroPanic(i8* undef) #2
++ call void @runtime.divideByZeroPanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.remInt(i32 %x, i32 %y, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.remInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp eq i32 %y, 0
+ br i1 %0, label %divbyzero.throw, label %divbyzero.next
+@@ -81,12 +83,12 @@ divbyzero.next: ; preds = %entry
+ ret i32 %5
+
+ divbyzero.throw: ; preds = %entry
+- call void @runtime.divideByZeroPanic(i8* undef) #2
++ call void @runtime.divideByZeroPanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.remUint(i32 %x, i32 %y, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.remUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp eq i32 %y, 0
+ br i1 %0, label %divbyzero.throw, label %divbyzero.next
+@@ -96,66 +98,66 @@ divbyzero.next: ; preds = %entry
+ ret i32 %1
+
+ divbyzero.throw: ; preds = %entry
+- call void @runtime.divideByZeroPanic(i8* undef) #2
++ call void @runtime.divideByZeroPanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.floatEQ(float %x, float %y, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.floatEQ(float %x, float %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = fcmp oeq float %x, %y
+ ret i1 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.floatNE(float %x, float %y, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.floatNE(float %x, float %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = fcmp une float %x, %y
+ ret i1 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.floatLower(float %x, float %y, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.floatLower(float %x, float %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = fcmp olt float %x, %y
+ ret i1 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.floatLowerEqual(float %x, float %y, i8* %context) unnamed_addr #1
{
++define hidden i1 @main.floatLowerEqual(float %x, float %y, ptr %context) unnamed_addr #1
{
+ entry:
+ %0 = fcmp ole float %x, %y
+ ret i1 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.floatGreater(float %x, float %y, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.floatGreater(float %x, float %y, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = fcmp ogt float %x, %y
+ ret i1 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.floatGreaterEqual(float %x, float %y, i8* %context) unnamed_addr
#1 {
++define hidden i1 @main.floatGreaterEqual(float %x, float %y, ptr %context) unnamed_addr
#1 {
+ entry:
+ %0 = fcmp oge float %x, %y
+ ret i1 %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden float @main.complexReal(float %x.r, float %x.i, i8* %context) unnamed_addr
#1 {
++define hidden float @main.complexReal(float %x.r, float %x.i, ptr %context) unnamed_addr
#1 {
+ entry:
+ ret float %x.r
+ }
+
+ ; Function Attrs: nounwind
+-define hidden float @main.complexImag(float %x.r, float %x.i, i8* %context) unnamed_addr
#1 {
++define hidden float @main.complexImag(float %x.r, float %x.i, ptr %context) unnamed_addr
#1 {
+ entry:
+ ret float %x.i
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r,
float %y.i, i8* %context) unnamed_addr #1 {
++define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r,
float %y.i, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = fadd float %x.r, %y.r
+ %1 = fadd float %x.i, %y.i
+@@ -165,7 +167,7 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r,
float %y.i, i8* %context) unnamed_addr #1 {
++define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r,
float %y.i, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = fsub float %x.r, %y.r
+ %1 = fsub float %x.i, %y.i
+@@ -175,7 +177,7 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r,
float %y.i, i8* %context) unnamed_addr #1 {
++define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r,
float %y.i, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = fmul float %x.r, %y.r
+ %1 = fmul float %x.i, %y.i
+@@ -189,15 +191,22 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.foo(%main.kv* dereferenceable_or_null(4) %a, i8* %context)
unnamed_addr #1 {
++define hidden void @main.foo(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @"main.foo$1"(%main.kv.0* null, i8* undef)
++ %complit = alloca %main.kv.0, align 8
++ store %main.kv.0 zeroinitializer, ptr %complit, align 8
++ call void @runtime.trackPointer(ptr nonnull %complit, ptr undef) #2
++ call void @"main.foo$1"(%main.kv.0 zeroinitializer, ptr undef)
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define internal void @"main.foo$1"(%main.kv.0* dereferenceable_or_null(1) %b,
i8* %context) unnamed_addr #1 {
++define internal void @"main.foo$1"(%main.kv.0 %b, ptr %context) unnamed_addr
#1 {
+ entry:
++ %b1 = alloca %main.kv.0, align 8
++ store %main.kv.0 zeroinitializer, ptr %b1, align 8
++ call void @runtime.trackPointer(ptr nonnull %b1, ptr undef) #2
++ store %main.kv.0 %b, ptr %b1, align 8
+ ret void
+ }
+
+diff --git a/compiler/testdata/channel.ll b/compiler/testdata/channel.ll
+index ec3dd6b9..8f4ed74e 100644
+--- a/compiler/testdata/channel.ll
++++ b/compiler/testdata/channel.ll
+@@ -3,110 +3,94 @@ source_filename = "channel.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8*
}
+-%runtime.channelBlockedList = type { %runtime.channelBlockedList*,
%"internal/task.Task"*, %runtime.chanSelectState*, {
%runtime.channelBlockedList*, i32, i32 } }
+-%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64,
%"internal/task.gcData", %"internal/task.state", i8* }
+-%"internal/task.gcData" = type { i8* }
+-%"internal/task.state" = type { i32, i8*,
%"internal/task.stackState", i1 }
+-%"internal/task.stackState" = type { i32, i32 }
+-%runtime.chanSelectState = type { %runtime.channel*, i8* }
++%runtime.channelBlockedList = type { ptr, ptr, ptr, { ptr, i32, i32 } }
++%runtime.chanSelectState = type { ptr, ptr }
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.chanIntSend(%runtime.channel* dereferenceable_or_null(32) %ch,
i8* %context) unnamed_addr #1 {
++define hidden void @main.chanIntSend(ptr dereferenceable_or_null(32) %ch, ptr %context)
unnamed_addr #1 {
+ entry:
+ %chan.blockedList = alloca %runtime.channelBlockedList, align 8
+ %chan.value = alloca i32, align 4
+- %chan.value.bitcast = bitcast i32* %chan.value to i8*
+- call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %chan.value.bitcast)
+- store i32 3, i32* %chan.value, align 4
+- %chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to
i8*
+- call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
+- call void @runtime.chanSend(%runtime.channel* %ch, i8* nonnull %chan.value.bitcast,
%runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3
+- call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
+- call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %chan.value.bitcast)
++ call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
++ store i32 3, ptr %chan.value, align 4
++ call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
++ call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull
%chan.blockedList, ptr undef) #3
++ call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
++ call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
+ ret void
+ }
+
+-; Function Attrs: argmemonly nofree nosync nounwind willreturn
+-declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2
++; Function Attrs: argmemonly nocallback nofree nosync nounwind willreturn
++declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
+
+-declare void @runtime.chanSend(%runtime.channel* dereferenceable_or_null(32), i8*,
%runtime.channelBlockedList* dereferenceable_or_null(24), i8*) #0
++declare void @runtime.chanSend(ptr dereferenceable_or_null(32), ptr, ptr
dereferenceable_or_null(24), ptr) #0
+
+-; Function Attrs: argmemonly nofree nosync nounwind willreturn
+-declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2
++; Function Attrs: argmemonly nocallback nofree nosync nounwind willreturn
++declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
+
+ ; Function Attrs: nounwind
+-define hidden void @main.chanIntRecv(%runtime.channel* dereferenceable_or_null(32) %ch,
i8* %context) unnamed_addr #1 {
++define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(32) %ch, ptr %context)
unnamed_addr #1 {
+ entry:
+ %chan.blockedList = alloca %runtime.channelBlockedList, align 8
+ %chan.value = alloca i32, align 4
+- %chan.value.bitcast = bitcast i32* %chan.value to i8*
+- call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %chan.value.bitcast)
+- %chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to
i8*
+- call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
+- %0 = call i1 @runtime.chanRecv(%runtime.channel* %ch, i8* nonnull %chan.value.bitcast,
%runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3
+- call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %chan.value.bitcast)
+- call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
++ call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
++ call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
++ %0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull
%chan.blockedList, ptr undef) #3
++ call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
++ call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
+ ret void
+ }
+
+-declare i1 @runtime.chanRecv(%runtime.channel* dereferenceable_or_null(32), i8*,
%runtime.channelBlockedList* dereferenceable_or_null(24), i8*) #0
++declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(32), ptr, ptr
dereferenceable_or_null(24), ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.chanZeroSend(%runtime.channel* dereferenceable_or_null(32) %ch,
i8* %context) unnamed_addr #1 {
++define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(32) %ch, ptr %context)
unnamed_addr #1 {
+ entry:
+ %complit = alloca {}, align 8
+ %chan.blockedList = alloca %runtime.channelBlockedList, align 8
+- %0 = bitcast {}* %complit to i8*
+- call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #3
+- %chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to
i8*
+- call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
+- call void @runtime.chanSend(%runtime.channel* %ch, i8* null,
%runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3
+- call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
++ call void @runtime.trackPointer(ptr nonnull %complit, ptr undef) #3
++ call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
++ call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.blockedList, ptr
undef) #3
++ call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.chanZeroRecv(%runtime.channel* dereferenceable_or_null(32) %ch,
i8* %context) unnamed_addr #1 {
++define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(32) %ch, ptr %context)
unnamed_addr #1 {
+ entry:
+ %chan.blockedList = alloca %runtime.channelBlockedList, align 8
+- %chan.blockedList.bitcast = bitcast %runtime.channelBlockedList* %chan.blockedList to
i8*
+- call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
+- %0 = call i1 @runtime.chanRecv(%runtime.channel* %ch, i8* null,
%runtime.channelBlockedList* nonnull %chan.blockedList, i8* undef) #3
+- call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %chan.blockedList.bitcast)
++ call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
++ %0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.blockedList, ptr
undef) #3
++ call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %chan.blockedList)
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.selectZeroRecv(%runtime.channel* dereferenceable_or_null(32)
%ch1, %runtime.channel* dereferenceable_or_null(32) %ch2, i8* %context) unnamed_addr #1 {
++define hidden void @main.selectZeroRecv(ptr dereferenceable_or_null(32) %ch1, ptr
dereferenceable_or_null(32) %ch2, ptr %context) unnamed_addr #1 {
+ entry:
+ %select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8
+ %select.send.value = alloca i32, align 4
+- store i32 1, i32* %select.send.value, align 4
+- %select.states.alloca.bitcast = bitcast [2 x %runtime.chanSelectState]*
%select.states.alloca to i8*
+- call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull
%select.states.alloca.bitcast)
+- %.repack = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x
%runtime.chanSelectState]* %select.states.alloca, i32 0, i32 0, i32 0
+- store %runtime.channel* %ch1, %runtime.channel** %.repack, align 8
+- %.repack1 = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x
%runtime.chanSelectState]* %select.states.alloca, i32 0, i32 0, i32 1
+- %0 = bitcast i8** %.repack1 to i32**
+- store i32* %select.send.value, i32** %0, align 4
+- %.repack3 = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x
%runtime.chanSelectState]* %select.states.alloca, i32 0, i32 1, i32 0
+- store %runtime.channel* %ch2, %runtime.channel** %.repack3, align 8
+- %.repack4 = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x
%runtime.chanSelectState]* %select.states.alloca, i32 0, i32 1, i32 1
+- store i8* null, i8** %.repack4, align 4
+- %select.states = getelementptr inbounds [2 x %runtime.chanSelectState], [2 x
%runtime.chanSelectState]* %select.states.alloca, i32 0, i32 0
+- %select.result = call { i32, i1 } @runtime.tryChanSelect(i8* undef,
%runtime.chanSelectState* nonnull %select.states, i32 2, i32 2, i8* undef) #3
+- call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %select.states.alloca.bitcast)
++ store i32 1, ptr %select.send.value, align 4
++ call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)
++ store ptr %ch1, ptr %select.states.alloca, align 8
++ %select.states.alloca.repack1 = getelementptr inbounds %runtime.chanSelectState, ptr
%select.states.alloca, i32 0, i32 1
++ store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4
++ %0 = getelementptr inbounds [2 x %runtime.chanSelectState], ptr %select.states.alloca,
i32 0, i32 1
++ store ptr %ch2, ptr %0, align 8
++ %.repack3 = getelementptr inbounds [2 x %runtime.chanSelectState], ptr
%select.states.alloca, i32 0, i32 1, i32 1
++ store ptr null, ptr %.repack3, align 4
++ %select.result = call { i32, i1 } @runtime.tryChanSelect(ptr undef, ptr nonnull
%select.states.alloca, i32 2, i32 2, ptr undef) #3
++ call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca)
+ %1 = extractvalue { i32, i1 } %select.result, 0
+ %2 = icmp eq i32 %1, 0
+ br i1 %2, label %select.done, label %select.next
+@@ -122,9 +106,9 @@ select.body: ; preds =
%select.next
+ br label %select.done
+ }
+
+-declare { i32, i1 } @runtime.tryChanSelect(i8*, %runtime.chanSelectState*, i32, i32,
i8*) #0
++declare { i32, i1 } @runtime.tryChanSelect(ptr, ptr, i32, i32, ptr) #0
+
+ attributes #0 = {
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+ attributes #1 = { nounwind
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+-attributes #2 = { argmemonly nofree nosync nounwind willreturn }
++attributes #2 = { argmemonly nocallback nofree nosync nounwind willreturn }
+ attributes #3 = { nounwind }
+diff --git a/compiler/testdata/defer-cortex-m-qemu.ll
b/compiler/testdata/defer-cortex-m-qemu.ll
+index 693f1b07..0841e255 100644
+--- a/compiler/testdata/defer-cortex-m-qemu.ll
++++ b/compiler/testdata/defer-cortex-m-qemu.ll
+@@ -3,103 +3,99 @@ source_filename = "defer.go"
+ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ target triple = "thumbv7m-unknown-unknown-eabi"
+
+-%runtime._defer = type { i32, %runtime._defer* }
+-%runtime.deferFrame = type { i8*, i8*, [0 x i8*], %runtime.deferFrame*, i1,
%runtime._interface }
+-%runtime._interface = type { i32, i8* }
++%runtime.deferFrame = type { ptr, ptr, [0 x ptr], ptr, i1, %runtime._interface }
++%runtime._interface = type { i32, ptr }
++%runtime._defer = type { i32, ptr }
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+-declare void @main.external(i8*) #0
++declare void @main.external(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.deferSimple(i8* %context) unnamed_addr #1 {
++define hidden void @main.deferSimple(ptr %context) unnamed_addr #1 {
+ entry:
+- %defer.alloca = alloca { i32, %runtime._defer* }, align 4
+- %deferPtr = alloca %runtime._defer*, align 4
+- store %runtime._defer* null, %runtime._defer** %deferPtr, align 4
++ %defer.alloca = alloca { i32, ptr }, align 4
++ %deferPtr = alloca ptr, align 4
++ store ptr null, ptr %deferPtr, align 4
+ %deferframe.buf = alloca %runtime.deferFrame, align 4
+- %0 = call i8* @llvm.stacksave()
+- call void @runtime.setupDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8*
%0, i8* undef) #3
+- %defer.alloca.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32,
%runtime._defer* }* %defer.alloca, i32 0, i32 0
+- store i32 0, i32* %defer.alloca.repack, align 4
+- %defer.alloca.repack16 = getelementptr inbounds { i32, %runtime._defer* }, { i32,
%runtime._defer* }* %defer.alloca, i32 0, i32 1
+- store %runtime._defer* null, %runtime._defer** %defer.alloca.repack16, align 4
+- %1 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
+- store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %1, align
4
+- %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
++ %0 = call ptr @llvm.stacksave()
++ call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #3
++ store i32 0, ptr %defer.alloca, align 4
++ %defer.alloca.repack15 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32
0, i32 1
++ store ptr null, ptr %defer.alloca.repack15, align 4
++ store ptr %defer.alloca, ptr %deferPtr, align 4
++ %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
+ %setjmp.result = icmp eq i32 %setjmp, 0
+- br i1 %setjmp.result, label %2, label %lpad
++ br i1 %setjmp.result, label %1, label %lpad
+
+-2: ; preds = %entry
+- call void @main.external(i8* undef) #3
++1: ; preds = %entry
++ call void @main.external(ptr undef) #3
+ br label %rundefers.loophead
+
+-rundefers.loophead: ; preds = %4, %2
+- %3 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4
+- %stackIsNil = icmp eq %runtime._defer* %3, null
++rundefers.loophead: ; preds = %3, %1
++ %2 = load ptr, ptr %deferPtr, align 4
++ %stackIsNil = icmp eq ptr %2, null
+ br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
+
+ rundefers.loop: ; preds = %rundefers.loophead
+- %stack.next.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %3, i32 0,
i32 1
+- %stack.next = load %runtime._defer*, %runtime._defer** %stack.next.gep, align 4
+- store %runtime._defer* %stack.next, %runtime._defer** %deferPtr, align 4
+- %callback.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %3, i32 0,
i32 0
+- %callback = load i32, i32* %callback.gep, align 4
++ %stack.next.gep = getelementptr inbounds %runtime._defer, ptr %2, i32 0, i32 1
++ %stack.next = load ptr, ptr %stack.next.gep, align 4
++ store ptr %stack.next, ptr %deferPtr, align 4
++ %callback = load i32, ptr %2, align 4
+ switch i32 %callback, label %rundefers.default [
+ i32 0, label %rundefers.callback0
+ ]
+
+ rundefers.callback0: ; preds = %rundefers.loop
+- %setjmp1 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
++ %setjmp1 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
+ %setjmp.result2 = icmp eq i32 %setjmp1, 0
+- br i1 %setjmp.result2, label %4, label %lpad
++ br i1 %setjmp.result2, label %3, label %lpad
+
+-4: ; preds = %rundefers.callback0
+- call void @"main.deferSimple$1"(i8* undef)
++3: ; preds = %rundefers.callback0
++ call void @"main.deferSimple$1"(ptr undef)
+ br label %rundefers.loophead
+
+ rundefers.default: ; preds = %rundefers.loop
+ unreachable
+
+ rundefers.end: ; preds = %rundefers.loophead
+- call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8*
undef) #3
++ call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
+ ret void
+
+ recover: ; preds = %rundefers.end3
+- call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8*
undef) #3
++ call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
+ ret void
+
+ lpad: ; preds = %rundefers.callback012,
%rundefers.callback0, %entry
+ br label %rundefers.loophead6
+
+-rundefers.loophead6: ; preds = %6, %lpad
+- %5 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4
+- %stackIsNil7 = icmp eq %runtime._defer* %5, null
++rundefers.loophead6: ; preds = %5, %lpad
++ %4 = load ptr, ptr %deferPtr, align 4
++ %stackIsNil7 = icmp eq ptr %4, null
+ br i1 %stackIsNil7, label %rundefers.end3, label %rundefers.loop5
+
+ rundefers.loop5: ; preds = %rundefers.loophead6
+- %stack.next.gep8 = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0,
i32 1
+- %stack.next9 = load %runtime._defer*, %runtime._defer** %stack.next.gep8, align 4
+- store %runtime._defer* %stack.next9, %runtime._defer** %deferPtr, align 4
+- %callback.gep10 = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0,
i32 0
+- %callback11 = load i32, i32* %callback.gep10, align 4
++ %stack.next.gep8 = getelementptr inbounds %runtime._defer, ptr %4, i32 0, i32 1
++ %stack.next9 = load ptr, ptr %stack.next.gep8, align 4
++ store ptr %stack.next9, ptr %deferPtr, align 4
++ %callback11 = load i32, ptr %4, align 4
+ switch i32 %callback11, label %rundefers.default4 [
+ i32 0, label %rundefers.callback012
+ ]
+
+ rundefers.callback012: ; preds = %rundefers.loop5
+- %setjmp14 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
+- %setjmp.result15 = icmp eq i32 %setjmp14, 0
+- br i1 %setjmp.result15, label %6, label %lpad
++ %setjmp13 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
++ %setjmp.result14 = icmp eq i32 %setjmp13, 0
++ br i1 %setjmp.result14, label %5, label %lpad
+
+-6: ; preds = %rundefers.callback012
+- call void @"main.deferSimple$1"(i8* undef)
++5: ; preds = %rundefers.callback012
++ call void @"main.deferSimple$1"(ptr undef)
+ br label %rundefers.loophead6
+
+ rundefers.default4: ; preds = %rundefers.loop5
+@@ -109,158 +105,151 @@ rundefers.end3: ; preds =
%rundefers.loophead6
+ br label %recover
+ }
+
+-; Function Attrs: nofree nosync nounwind willreturn
+-declare i8* @llvm.stacksave() #2
++; Function Attrs: nocallback nofree nosync nounwind willreturn
++declare ptr @llvm.stacksave() #2
+
+-declare void @runtime.setupDeferFrame(%runtime.deferFrame* dereferenceable_or_null(24),
i8*, i8*) #0
++declare void @runtime.setupDeferFrame(ptr dereferenceable_or_null(24), ptr, ptr) #0
+
+ ; Function Attrs: nounwind
+-define internal void @"main.deferSimple$1"(i8* %context) unnamed_addr #1 {
++define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.printint32(i32 3, i8* undef) #3
++ call void @runtime.printint32(i32 3, ptr undef) #3
+ ret void
+ }
+
+-declare void @runtime.destroyDeferFrame(%runtime.deferFrame*
dereferenceable_or_null(24), i8*) #0
++declare void @runtime.destroyDeferFrame(ptr dereferenceable_or_null(24), ptr) #0
+
+-declare void @runtime.printint32(i32, i8*) #0
++declare void @runtime.printint32(i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.deferMultiple(i8* %context) unnamed_addr #1 {
++define hidden void @main.deferMultiple(ptr %context) unnamed_addr #1 {
+ entry:
+- %defer.alloca2 = alloca { i32, %runtime._defer* }, align 4
+- %defer.alloca = alloca { i32, %runtime._defer* }, align 4
+- %deferPtr = alloca %runtime._defer*, align 4
+- store %runtime._defer* null, %runtime._defer** %deferPtr, align 4
++ %defer.alloca2 = alloca { i32, ptr }, align 4
++ %defer.alloca = alloca { i32, ptr }, align 4
++ %deferPtr = alloca ptr, align 4
++ store ptr null, ptr %deferPtr, align 4
+ %deferframe.buf = alloca %runtime.deferFrame, align 4
+- %0 = call i8* @llvm.stacksave()
+- call void @runtime.setupDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8*
%0, i8* undef) #3
+- %defer.alloca.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32,
%runtime._defer* }* %defer.alloca, i32 0, i32 0
+- store i32 0, i32* %defer.alloca.repack, align 4
+- %defer.alloca.repack26 = getelementptr inbounds { i32, %runtime._defer* }, { i32,
%runtime._defer* }* %defer.alloca, i32 0, i32 1
+- store %runtime._defer* null, %runtime._defer** %defer.alloca.repack26, align 4
+- %1 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
+- store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %1, align
4
+- %defer.alloca2.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32,
%runtime._defer* }* %defer.alloca2, i32 0, i32 0
+- store i32 1, i32* %defer.alloca2.repack, align 4
+- %defer.alloca2.repack27 = getelementptr inbounds { i32, %runtime._defer* }, { i32,
%runtime._defer* }* %defer.alloca2, i32 0, i32 1
+- %2 = bitcast %runtime._defer** %defer.alloca2.repack27 to { i32, %runtime._defer* }**
+- store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %2, align
4
+- %3 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
+- store { i32, %runtime._defer* }* %defer.alloca2, { i32, %runtime._defer* }** %3, align
4
+- %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
++ %0 = call ptr @llvm.stacksave()
++ call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #3
++ store i32 0, ptr %defer.alloca, align 4
++ %defer.alloca.repack22 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32
0, i32 1
++ store ptr null, ptr %defer.alloca.repack22, align 4
++ store ptr %defer.alloca, ptr %deferPtr, align 4
++ store i32 1, ptr %defer.alloca2, align 4
++ %defer.alloca2.repack23 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca2, i32
0, i32 1
++ store ptr %defer.alloca, ptr %defer.alloca2.repack23, align 4
++ store ptr %defer.alloca2, ptr %deferPtr, align 4
++ %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
+ %setjmp.result = icmp eq i32 %setjmp, 0
+- br i1 %setjmp.result, label %4, label %lpad
++ br i1 %setjmp.result, label %1, label %lpad
+
+-4: ; preds = %entry
+- call void @main.external(i8* undef) #3
++1: ; preds = %entry
++ call void @main.external(ptr undef) #3
+ br label %rundefers.loophead
+
+-rundefers.loophead: ; preds = %7, %6, %4
+- %5 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4
+- %stackIsNil = icmp eq %runtime._defer* %5, null
++rundefers.loophead: ; preds = %4, %3, %1
++ %2 = load ptr, ptr %deferPtr, align 4
++ %stackIsNil = icmp eq ptr %2, null
+ br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
+
+ rundefers.loop: ; preds = %rundefers.loophead
+- %stack.next.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0,
i32 1
+- %stack.next = load %runtime._defer*, %runtime._defer** %stack.next.gep, align 4
+- store %runtime._defer* %stack.next, %runtime._defer** %deferPtr, align 4
+- %callback.gep = getelementptr inbounds %runtime._defer, %runtime._defer* %5, i32 0,
i32 0
+- %callback = load i32, i32* %callback.gep, align 4
++ %stack.next.gep = getelementptr inbounds %runtime._defer, ptr %2, i32 0, i32 1
++ %stack.next = load ptr, ptr %stack.next.gep, align 4
++ store ptr %stack.next, ptr %deferPtr, align 4
++ %callback = load i32, ptr %2, align 4
+ switch i32 %callback, label %rundefers.default [
+ i32 0, label %rundefers.callback0
+ i32 1, label %rundefers.callback1
+ ]
+
+ rundefers.callback0: ; preds = %rundefers.loop
+- %setjmp4 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
+- %setjmp.result5 = icmp eq i32 %setjmp4, 0
+- br i1 %setjmp.result5, label %6, label %lpad
++ %setjmp3 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
++ %setjmp.result4 = icmp eq i32 %setjmp3, 0
++ br i1 %setjmp.result4, label %3, label %lpad
+
+-6: ; preds = %rundefers.callback0
+- call void @"main.deferMultiple$1"(i8* undef)
++3: ; preds = %rundefers.callback0
++ call void @"main.deferMultiple$1"(ptr undef)
+ br label %rundefers.loophead
+
+ rundefers.callback1: ; preds = %rundefers.loop
+- %setjmp7 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
+- %setjmp.result8 = icmp eq i32 %setjmp7, 0
+- br i1 %setjmp.result8, label %7, label %lpad
++ %setjmp5 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
++ %setjmp.result6 = icmp eq i32 %setjmp5, 0
++ br i1 %setjmp.result6, label %4, label %lpad
+
+-7: ; preds = %rundefers.callback1
+- call void @"main.deferMultiple$2"(i8* undef)
++4: ; preds = %rundefers.callback1
++ call void @"main.deferMultiple$2"(ptr undef)
+ br label %rundefers.loophead
+
+ rundefers.default: ; preds = %rundefers.loop
+ unreachable
+
+ rundefers.end: ; preds = %rundefers.loophead
+- call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8*
undef) #3
++ call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
+ ret void
+
+-recover: ; preds = %rundefers.end9
+- call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8*
undef) #3
++recover: ; preds = %rundefers.end7
++ call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #3
+ ret void
+
+-lpad: ; preds = %rundefers.callback122,
%rundefers.callback018, %rundefers.callback1, %rundefers.callback0, %entry
+- br label %rundefers.loophead12
+-
+-rundefers.loophead12: ; preds = %10, %9, %lpad
+- %8 = load %runtime._defer*, %runtime._defer** %deferPtr, align 4
+- %stackIsNil13 = icmp eq %runtime._defer* %8, null
+- br i1 %stackIsNil13, label %rundefers.end9, label %rundefers.loop11
+-
+-rundefers.loop11: ; preds = %rundefers.loophead12
+- %stack.next.gep14 = getelementptr inbounds %runtime._defer, %runtime._defer* %8, i32
0, i32 1
+- %stack.next15 = load %runtime._defer*, %runtime._defer** %stack.next.gep14, align 4
+- store %runtime._defer* %stack.next15, %runtime._defer** %deferPtr, align 4
+- %callback.gep16 = getelementptr inbounds %runtime._defer, %runtime._defer* %8, i32 0,
i32 0
+- %callback17 = load i32, i32* %callback.gep16, align 4
+- switch i32 %callback17, label %rundefers.default10 [
+- i32 0, label %rundefers.callback018
+- i32 1, label %rundefers.callback122
++lpad: ; preds = %rundefers.callback119,
%rundefers.callback016, %rundefers.callback1, %rundefers.callback0, %entry
++ br label %rundefers.loophead10
++
++rundefers.loophead10: ; preds = %7, %6, %lpad
++ %5 = load ptr, ptr %deferPtr, align 4
++ %stackIsNil11 = icmp eq ptr %5, null
++ br i1 %stackIsNil11, label %rundefers.end7, label %rundefers.loop9
++
++rundefers.loop9: ; preds = %rundefers.loophead10
++ %stack.next.gep12 = getelementptr inbounds %runtime._defer, ptr %5, i32 0, i32 1
++ %stack.next13 = load ptr, ptr %stack.next.gep12, align 4
++ store ptr %stack.next13, ptr %deferPtr, align 4
++ %callback15 = load i32, ptr %5, align 4
++ switch i32 %callback15, label %rundefers.default8 [
++ i32 0, label %rundefers.callback016
++ i32 1, label %rundefers.callback119
+ ]
+
+-rundefers.callback018: ; preds = %rundefers.loop11
+- %setjmp20 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
+- %setjmp.result21 = icmp eq i32 %setjmp20, 0
+- br i1 %setjmp.result21, label %9, label %lpad
++rundefers.callback016: ; preds = %rundefers.loop9
++ %setjmp17 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
++ %setjmp.result18 = icmp eq i32 %setjmp17, 0
++ br i1 %setjmp.result18, label %6, label %lpad
+
+-9: ; preds = %rundefers.callback018
+- call void @"main.deferMultiple$1"(i8* undef)
+- br label %rundefers.loophead12
++6: ; preds = %rundefers.callback016
++ call void @"main.deferMultiple$1"(ptr undef)
++ br label %rundefers.loophead10
+
+-rundefers.callback122: ; preds = %rundefers.loop11
+- %setjmp24 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame*
nonnull %deferframe.buf) #4
+- %setjmp.result25 = icmp eq i32 %setjmp24, 0
+- br i1 %setjmp.result25, label %10, label %lpad
++rundefers.callback119: ; preds = %rundefers.loop9
++ %setjmp20 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]",
"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr
nonnull %deferframe.buf) #4
++ %setjmp.result21 = icmp eq i32 %setjmp20, 0
++ br i1 %setjmp.result21, label %7, label %lpad
+
+-10: ; preds = %rundefers.callback122
+- call void @"main.deferMultiple$2"(i8* undef)
+- br label %rundefers.loophead12
++7: ; preds = %rundefers.callback119
++ call void @"main.deferMultiple$2"(ptr undef)
++ br label %rundefers.loophead10
+
+-rundefers.default10: ; preds = %rundefers.loop11
++rundefers.default8: ; preds = %rundefers.loop9
+ unreachable
+
+-rundefers.end9: ; preds = %rundefers.loophead12
++rundefers.end7: ; preds = %rundefers.loophead10
+ br label %recover
+ }
+
+ ; Function Attrs: nounwind
+-define internal void @"main.deferMultiple$1"(i8* %context) unnamed_addr #1 {
++define internal void @"main.deferMultiple$1"(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.printint32(i32 3, i8* undef) #3
++ call void @runtime.printint32(i32 3, ptr undef) #3
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define internal void @"main.deferMultiple$2"(i8* %context) unnamed_addr #1 {
++define internal void @"main.deferMultiple$2"(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.printint32(i32 5, i8* undef) #3
++ call void @runtime.printint32(i32 5, ptr undef) #3
+ ret void
+ }
+
+ attributes #0 = {
"target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
+ attributes #1 = { nounwind
"target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
+-attributes #2 = { nofree nosync nounwind willreturn }
++attributes #2 = { nocallback nofree nosync nounwind willreturn }
+ attributes #3 = { nounwind }
+ attributes #4 = { nounwind returns_twice }
+diff --git a/compiler/testdata/float.ll b/compiler/testdata/float.ll
+index 0ecd21e9..2acc2ed4 100644
+--- a/compiler/testdata/float.ll
++++ b/compiler/testdata/float.ll
+@@ -3,18 +3,18 @@ source_filename = "float.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.f32tou32(float %v, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.f32tou32(float %v, ptr %context) unnamed_addr #1 {
+ entry:
+ %positive = fcmp oge float %v, 0.000000e+00
+ %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
+@@ -26,25 +26,25 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden float @main.maxu32f(i8* %context) unnamed_addr #1 {
++define hidden float @main.maxu32f(ptr %context) unnamed_addr #1 {
+ entry:
+ ret float 0x41F0000000000000
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.maxu32tof32(i8* %context) unnamed_addr #1 {
++define hidden i32 @main.maxu32tof32(ptr %context) unnamed_addr #1 {
+ entry:
+ ret i32 -1
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { i32, i32, i32, i32 } @main.inftoi32(i8* %context) unnamed_addr #1 {
++define hidden { i32, i32, i32, i32 } @main.inftoi32(ptr %context) unnamed_addr #1 {
+ entry:
+ ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 }
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.u32tof32tou32(i32 %v, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.u32tof32tou32(i32 %v, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = uitofp i32 %v to float
+ %withinmax = fcmp ole float %0, 0x41EFFFFFC0000000
+@@ -54,7 +54,7 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden float @main.f32tou32tof32(float %v, i8* %context) unnamed_addr #1 {
++define hidden float @main.f32tou32tof32(float %v, ptr %context) unnamed_addr #1 {
+ entry:
+ %positive = fcmp oge float %v, 0.000000e+00
+ %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
+@@ -67,7 +67,7 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8 @main.f32tou8(float %v, i8* %context) unnamed_addr #1 {
++define hidden i8 @main.f32tou8(float %v, ptr %context) unnamed_addr #1 {
+ entry:
+ %positive = fcmp oge float %v, 0.000000e+00
+ %withinmax = fcmp ole float %v, 2.550000e+02
+@@ -79,7 +79,7 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8 @main.f32toi8(float %v, i8* %context) unnamed_addr #1 {
++define hidden i8 @main.f32toi8(float %v, ptr %context) unnamed_addr #1 {
+ entry:
+ %abovemin = fcmp oge float %v, -1.280000e+02
+ %belowmax = fcmp ole float %v, 1.270000e+02
+diff --git a/compiler/testdata/func.ll b/compiler/testdata/func.ll
+index 2ed16eaf..227e52c1 100644
+--- a/compiler/testdata/func.ll
++++ b/compiler/testdata/func.ll
+@@ -3,43 +3,42 @@ source_filename = "func.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.foo(i8* %callback.context, void ()* %callback.funcptr, i8*
%context) unnamed_addr #1 {
++define hidden void @main.foo(ptr %callback.context, ptr %callback.funcptr, ptr %context)
unnamed_addr #1 {
+ entry:
+- %0 = icmp eq void ()* %callback.funcptr, null
++ %0 = icmp eq ptr %callback.funcptr, null
+ br i1 %0, label %fpcall.throw, label %fpcall.next
+
+ fpcall.next: ; preds = %entry
+- %1 = bitcast void ()* %callback.funcptr to void (i32, i8*)*
+- call void %1(i32 3, i8* %callback.context) #2
++ call void %callback.funcptr(i32 3, ptr %callback.context) #2
+ ret void
+
+ fpcall.throw: ; preds = %entry
+- call void @runtime.nilPanic(i8* undef) #2
++ call void @runtime.nilPanic(ptr undef) #2
+ unreachable
+ }
+
+-declare void @runtime.nilPanic(i8*) #0
++declare void @runtime.nilPanic(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.bar(i8* %context) unnamed_addr #1 {
++define hidden void @main.bar(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @main.foo(i8* undef, void ()* bitcast (void (i32, i8*)* @main.someFunc to
void ()*), i8* undef)
++ call void @main.foo(ptr undef, ptr nonnull @main.someFunc, ptr undef)
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.someFunc(i32 %arg0, i8* %context) unnamed_addr #1 {
++define hidden void @main.someFunc(i32 %arg0, ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+diff --git a/compiler/testdata/gc.ll b/compiler/testdata/gc.ll
+index 26bc4c24..e54b207d 100644
+--- a/compiler/testdata/gc.ll
++++ b/compiler/testdata/gc.ll
+@@ -3,133 +3,129 @@ source_filename = "gc.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*,
%runtime.typecodeID*, i32 }
+-%runtime.interfaceMethodInfo = type { i8*, i32 }
+-%runtime._interface = type { i32, i8* }
++%runtime.typecodeID = type { ptr, i32, ptr, ptr, i32 }
++%runtime._interface = type { i32, ptr }
+
+-(a)main.scalar1 = hidden global i8* null, align 4
+-(a)main.scalar2 = hidden global i32* null, align 4
+-(a)main.scalar3 = hidden global i64* null, align 4
+-(a)main.scalar4 = hidden global float* null, align 4
+-(a)main.array1 = hidden global [3 x i8]* null, align 4
+-(a)main.array2 = hidden global [71 x i8]* null, align 4
+-(a)main.array3 = hidden global [3 x i8*]* null, align 4
+-(a)main.struct1 = hidden global {}* null, align 4
+-(a)main.struct2 = hidden global { i32, i32 }* null, align 4
+-(a)main.struct3 = hidden global { i8*, [60 x i32], i8* }* null, align 4
+-(a)main.struct4 = hidden global { i8*, [61 x i32] }* null, align 4
+-(a)main.slice1 = hidden global { i8*, i32, i32 } zeroinitializer, align 8
+-(a)main.slice2 = hidden global { i32**, i32, i32 } zeroinitializer, align 8
+-(a)main.slice3 = hidden global { { i8*, i32, i32 }*, i32, i32 } zeroinitializer, align 8
++(a)main.scalar1 = hidden global ptr null, align 4
++(a)main.scalar2 = hidden global ptr null, align 4
++(a)main.scalar3 = hidden global ptr null, align 4
++(a)main.scalar4 = hidden global ptr null, align 4
++(a)main.array1 = hidden global ptr null, align 4
++(a)main.array2 = hidden global ptr null, align 4
++(a)main.array3 = hidden global ptr null, align 4
++(a)main.struct1 = hidden global ptr null, align 4
++(a)main.struct2 = hidden global ptr null, align 4
++(a)main.struct3 = hidden global ptr null, align 4
++(a)main.struct4 = hidden global ptr null, align 4
++(a)main.slice1 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
++(a)main.slice2 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
++(a)main.slice3 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
+ @"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant
{ i32, [8 x i8] } { i32 62, [8 x i8] c" \00\00\00\00\00\00\01" }
+ @"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x
i8] } { i32 62, [8 x i8] c"\00\00\00\00\00\00\00\01" }
+-@"reflect/types.type:basic:complex128" = linkonce_odr constant
%runtime.typecodeID { %runtime.typecodeID* null, i32 0, %runtime.interfaceMethodInfo*
null, %runtime.typecodeID* @"reflect/types.type:pointer:basic:complex128", i32 0
}
+-@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant
%runtime.typecodeID { %runtime.typecodeID*
@"reflect/types.type:basic:complex128", i32 0, %runtime.interfaceMethodInfo*
null, %runtime.typecodeID* null, i32 0 }
++@"reflect/types.type:basic:complex128" = linkonce_odr constant
%runtime.typecodeID { ptr null, i32 0, ptr null, ptr
@"reflect/types.type:pointer:basic:complex128", i32 0 }
++@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant
%runtime.typecodeID { ptr @"reflect/types.type:basic:complex128", i32 0, ptr
null, ptr null, i32 0 }
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.newScalar(i8* %context) unnamed_addr #1 {
++define hidden void @main.newScalar(ptr %context) unnamed_addr #1 {
+ entry:
+- %new = call i8* @runtime.alloc(i32 1, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#2
+- call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2
+- store i8* %new, i8** @main.scalar1, align 4
+- %new1 = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#2
+- call void @runtime.trackPointer(i8* nonnull %new1, i8* undef) #2
+- store i8* %new1, i8** bitcast (i32** @main.scalar2 to i8**), align 4
+- %new2 = call i8* @runtime.alloc(i32 8, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#2
+- call void @runtime.trackPointer(i8* nonnull %new2, i8* undef) #2
+- store i8* %new2, i8** bitcast (i64** @main.scalar3 to i8**), align 4
+- %new3 = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#2
+- call void @runtime.trackPointer(i8* nonnull %new3, i8* undef) #2
+- store i8* %new3, i8** bitcast (float** @main.scalar4 to i8**), align 4
++ %new = call ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#2
++ call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
++ store ptr %new, ptr @main.scalar1, align 4
++ %new1 = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#2
++ call void @runtime.trackPointer(ptr nonnull %new1, ptr undef) #2
++ store ptr %new1, ptr @main.scalar2, align 4
++ %new2 = call ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#2
++ call void @runtime.trackPointer(ptr nonnull %new2, ptr undef) #2
++ store ptr %new2, ptr @main.scalar3, align 4
++ %new3 = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#2
++ call void @runtime.trackPointer(ptr nonnull %new3, ptr undef) #2
++ store ptr %new3, ptr @main.scalar4, align 4
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.newArray(i8* %context) unnamed_addr #1 {
++define hidden void @main.newArray(ptr %context) unnamed_addr #1 {
+ entry:
+- %new = call i8* @runtime.alloc(i32 3, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#2
+- call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2
+- store i8* %new, i8** bitcast ([3 x i8]** @main.array1 to i8**), align 4
+- %new1 = call i8* @runtime.alloc(i32 71, i8* nonnull inttoptr (i32 3 to i8*), i8*
undef) #2
+- call void @runtime.trackPointer(i8* nonnull %new1, i8* undef) #2
+- store i8* %new1, i8** bitcast ([71 x i8]** @main.array2 to i8**), align 4
+- %new2 = call i8* @runtime.alloc(i32 12, i8* nonnull inttoptr (i32 67 to i8*), i8*
undef) #2
+- call void @runtime.trackPointer(i8* nonnull %new2, i8* undef) #2
+- store i8* %new2, i8** bitcast ([3 x i8*]** @main.array3 to i8**), align 4
++ %new = call ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#2
++ call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
++ store ptr %new, ptr @main.array1, align 4
++ %new1 = call ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr
undef) #2
++ call void @runtime.trackPointer(ptr nonnull %new1, ptr undef) #2
++ store ptr %new1, ptr @main.array2, align 4
++ %new2 = call ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr
undef) #2
++ call void @runtime.trackPointer(ptr nonnull %new2, ptr undef) #2
++ store ptr %new2, ptr @main.array3, align 4
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.newStruct(i8* %context) unnamed_addr #1 {
++define hidden void @main.newStruct(ptr %context) unnamed_addr #1 {
+ entry:
+- %new = call i8* @runtime.alloc(i32 0, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#2
+- call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2
+- store i8* %new, i8** bitcast ({}** @main.struct1 to i8**), align 4
+- %new1 = call i8* @runtime.alloc(i32 8, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#2
+- call void @runtime.trackPointer(i8* nonnull %new1, i8* undef) #2
+- store i8* %new1, i8** bitcast ({ i32, i32 }** @main.struct2 to i8**), align 4
+- %new2 = call i8* @runtime.alloc(i32 248, i8* bitcast ({ i32, [8 x i8] }*
@"runtime/gc.layout:62-2000000000000001" to i8*), i8* undef) #2
+- call void @runtime.trackPointer(i8* nonnull %new2, i8* undef) #2
+- store i8* %new2, i8** bitcast ({ i8*, [60 x i32], i8* }** @main.struct3 to i8**),
align 4
+- %new3 = call i8* @runtime.alloc(i32 248, i8* bitcast ({ i32, [8 x i8] }*
@"runtime/gc.layout:62-0001" to i8*), i8* undef) #2
+- call void @runtime.trackPointer(i8* nonnull %new3, i8* undef) #2
+- store i8* %new3, i8** bitcast ({ i8*, [61 x i32] }** @main.struct4 to i8**), align 4
++ %new = call ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#2
++ call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
++ store ptr %new, ptr @main.struct1, align 4
++ %new1 = call ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#2
++ call void @runtime.trackPointer(ptr nonnull %new1, ptr undef) #2
++ store ptr %new1, ptr @main.struct2, align 4
++ %new2 = call ptr @runtime.alloc(i32 248, ptr nonnull
@"runtime/gc.layout:62-2000000000000001", ptr undef) #2
++ call void @runtime.trackPointer(ptr nonnull %new2, ptr undef) #2
++ store ptr %new2, ptr @main.struct3, align 4
++ %new3 = call ptr @runtime.alloc(i32 248, ptr nonnull
@"runtime/gc.layout:62-0001", ptr undef) #2
++ call void @runtime.trackPointer(ptr nonnull %new3, ptr undef) #2
++ store ptr %new3, ptr @main.struct4, align 4
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { i8*, void ()* }* @main.newFuncValue(i8* %context) unnamed_addr #1 {
++define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #1 {
+ entry:
+- %new = call i8* @runtime.alloc(i32 8, i8* nonnull inttoptr (i32 197 to i8*), i8*
undef) #2
+- %0 = bitcast i8* %new to { i8*, void ()* }*
+- call void @runtime.trackPointer(i8* nonnull %new, i8* undef) #2
+- ret { i8*, void ()* }* %0
++ %new = call ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr
undef) #2
++ call void @runtime.trackPointer(ptr nonnull %new, ptr undef) #2
++ ret ptr %new
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.makeSlice(i8* %context) unnamed_addr #1 {
++define hidden void @main.makeSlice(ptr %context) unnamed_addr #1 {
+ entry:
+- %makeslice = call i8* @runtime.alloc(i32 5, i8* nonnull inttoptr (i32 3 to i8*), i8*
undef) #2
+- call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2
+- store i8* %makeslice, i8** getelementptr inbounds ({ i8*, i32, i32 }, { i8*, i32, i32
}* @main.slice1, i32 0, i32 0), align 8
+- store i32 5, i32* getelementptr inbounds ({ i8*, i32, i32 }, { i8*, i32, i32 }*
@main.slice1, i32 0, i32 1), align 4
+- store i32 5, i32* getelementptr inbounds ({ i8*, i32, i32 }, { i8*, i32, i32 }*
@main.slice1, i32 0, i32 2), align 8
+- %makeslice1 = call i8* @runtime.alloc(i32 20, i8* nonnull inttoptr (i32 67 to i8*),
i8* undef) #2
+- call void @runtime.trackPointer(i8* nonnull %makeslice1, i8* undef) #2
+- store i8* %makeslice1, i8** bitcast ({ i32**, i32, i32 }* @main.slice2 to i8**), align
8
+- store i32 5, i32* getelementptr inbounds ({ i32**, i32, i32 }, { i32**, i32, i32 }*
@main.slice2, i32 0, i32 1), align 4
+- store i32 5, i32* getelementptr inbounds ({ i32**, i32, i32 }, { i32**, i32, i32 }*
@main.slice2, i32 0, i32 2), align 8
+- %makeslice3 = call i8* @runtime.alloc(i32 60, i8* nonnull inttoptr (i32 71 to i8*),
i8* undef) #2
+- call void @runtime.trackPointer(i8* nonnull %makeslice3, i8* undef) #2
+- store i8* %makeslice3, i8** bitcast ({ { i8*, i32, i32 }*, i32, i32 }* @main.slice3 to
i8**), align 8
+- store i32 5, i32* getelementptr inbounds ({ { i8*, i32, i32 }*, i32, i32 }, { { i8*,
i32, i32 }*, i32, i32 }* @main.slice3, i32 0, i32 1), align 4
+- store i32 5, i32* getelementptr inbounds ({ { i8*, i32, i32 }*, i32, i32 }, { { i8*,
i32, i32 }*, i32, i32 }* @main.slice3, i32 0, i32 2), align 8
++ %makeslice = call ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr
undef) #2
++ call void @runtime.trackPointer(ptr nonnull %makeslice, ptr undef) #2
++ store ptr %makeslice, ptr @main.slice1, align 8
++ store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0,
i32 1), align 4
++ store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0,
i32 2), align 8
++ %makeslice1 = call ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr),
ptr undef) #2
++ call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr undef) #2
++ store ptr %makeslice1, ptr @main.slice2, align 8
++ store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0,
i32 1), align 4
++ store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0,
i32 2), align 8
++ %makeslice3 = call ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr),
ptr undef) #2
++ call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr undef) #2
++ store ptr %makeslice3, ptr @main.slice3, align 8
++ store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0,
i32 1), align 4
++ store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0,
i32 2), align 8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, i8*
%context) unnamed_addr #1 {
++define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr
%context) unnamed_addr #1 {
+ entry:
+- %0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef) #2
+- call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2
+- %.repack = bitcast i8* %0 to double*
+- store double %v.r, double* %.repack, align 8
+- %.repack1 = getelementptr inbounds i8, i8* %0, i32 8
+- %1 = bitcast i8* %.repack1 to double*
+- store double %v.i, double* %1, align 8
+- %2 = insertvalue %runtime._interface { i32 ptrtoint (%runtime.typecodeID*
@"reflect/types.type:basic:complex128" to i32), i8* undef }, i8* %0, 1
+- call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2
+- ret %runtime._interface %2
++ %0 = call ptr @runtime.alloc(i32 16, ptr null, ptr undef) #2
++ call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
++ store double %v.r, ptr %0, align 8
++ %.repack1 = getelementptr inbounds { double, double }, ptr %0, i32 0, i32 1
++ store double %v.i, ptr %.repack1, align 8
++ %1 = insertvalue %runtime._interface { i32 ptrtoint (ptr
@"reflect/types.type:basic:complex128" to i32), ptr undef }, ptr %0, 1
++ call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
++ ret %runtime._interface %1
+ }
+
+ attributes #0 = {
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+diff --git a/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll
b/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll
+index edd4d666..ac1adaff 100644
+--- a/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll
++++ b/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll
+@@ -3,201 +3,176 @@ source_filename = "goroutine.go"
+ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ target triple = "thumbv7m-unknown-unknown-eabi"
+
+-%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8*
}
+-%runtime.channelBlockedList = type { %runtime.channelBlockedList*,
%"internal/task.Task"*, %runtime.chanSelectState*, {
%runtime.channelBlockedList*, i32, i32 } }
+-%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64,
%"internal/task.gcData", %"internal/task.state", i8* }
+-%"internal/task.gcData" = type {}
+-%"internal/task.state" = type { i32, i32* }
+-%runtime.chanSelectState = type { %runtime.channel*, i8* }
++%runtime._string = type { ptr, i32 }
+
+ @"main$string" = internal unnamed_addr constant [4 x i8] c"test",
align 1
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.regularFunctionGoroutine(i8* %context) unnamed_addr #1 {
++define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
+ entry:
+- %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(void (i8*)* @"main.regularFunction$gowrapper" to i32), i8* undef) #8
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"main.regularFunction$gowrapper" to i32), i8* nonnull inttoptr (i32 5 to i8*),
i32 %stacksize, i8* undef) #8
++ %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(ptr @"main.regularFunction$gowrapper" to i32), ptr undef) #8
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr),
i32 %stacksize, ptr undef) #8
+ ret void
+ }
+
+-declare void @main.regularFunction(i32, i8*) #0
++declare void @main.regularFunction(i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @"main.regularFunction$gowrapper"(i8* %0)
unnamed_addr #2 {
++define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0)
unnamed_addr #2 {
+ entry:
+- %unpack.int = ptrtoint i8* %0 to i32
+- call void @main.regularFunction(i32 %unpack.int, i8* undef) #8
++ %unpack.int = ptrtoint ptr %0 to i32
++ call void @main.regularFunction(i32 %unpack.int, ptr undef) #8
+ ret void
+ }
+
+-declare i32 @"internal/task.getGoroutineStackSize"(i32, i8*) #0
++declare i32 @"internal/task.getGoroutineStackSize"(i32, ptr) #0
+
+-declare void @"internal/task.start"(i32, i8*, i32, i8*) #0
++declare void @"internal/task.start"(i32, ptr, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.inlineFunctionGoroutine(i8* %context) unnamed_addr #1 {
++define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
+ entry:
+- %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(void (i8*)* @"main.inlineFunctionGoroutine$1$gowrapper" to i32), i8* undef) #8
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"main.inlineFunctionGoroutine$1$gowrapper" to i32), i8* nonnull inttoptr (i32 5
to i8*), i32 %stacksize, i8* undef) #8
++ %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr undef) #8
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5
to ptr), i32 %stacksize, ptr undef) #8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context)
unnamed_addr #1 {
++define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context)
unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(i8* %0)
unnamed_addr #3 {
++define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(ptr %0)
unnamed_addr #3 {
+ entry:
+- %unpack.int = ptrtoint i8* %0 to i32
+- call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, i8* undef)
++ %unpack.int = ptrtoint ptr %0 to i32
++ call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, ptr undef)
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.closureFunctionGoroutine(i8* %context) unnamed_addr #1 {
++define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
+ entry:
+- %n = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#8
+- %0 = bitcast i8* %n to i32*
+- store i32 3, i32* %0, align 4
+- %1 = call i8* @runtime.alloc(i32 8, i8* null, i8* undef) #8
+- %2 = bitcast i8* %1 to i32*
+- store i32 5, i32* %2, align 4
+- %3 = getelementptr inbounds i8, i8* %1, i32 4
+- %4 = bitcast i8* %3 to i8**
+- store i8* %n, i8** %4, align 4
+- %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(void (i8*)* @"main.closureFunctionGoroutine$1$gowrapper" to i32), i8* undef)
#8
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"main.closureFunctionGoroutine$1$gowrapper" to i32), i8* nonnull %1, i32
%stacksize, i8* undef) #8
+- %5 = load i32, i32* %0, align 4
+- call void @runtime.printint32(i32 %5, i8* undef) #8
++ %n = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#8
++ store i32 3, ptr %n, align 4
++ %0 = call ptr @runtime.alloc(i32 8, ptr null, ptr undef) #8
++ store i32 5, ptr %0, align 4
++ %1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
++ store ptr %n, ptr %1, align 4
++ %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #8
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32
%stacksize, ptr undef) #8
++ %2 = load i32, ptr %n, align 4
++ call void @runtime.printint32(i32 %2, ptr undef) #8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define internal void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context)
unnamed_addr #1 {
++define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context)
unnamed_addr #1 {
+ entry:
+- %unpack.ptr = bitcast i8* %context to i32*
+- store i32 7, i32* %unpack.ptr, align 4
++ store i32 7, ptr %context, align 4
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(i8* %0)
unnamed_addr #4 {
++define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0)
unnamed_addr #4 {
+ entry:
+- %1 = bitcast i8* %0 to i32*
+- %2 = load i32, i32* %1, align 4
+- %3 = getelementptr inbounds i8, i8* %0, i32 4
+- %4 = bitcast i8* %3 to i8**
+- %5 = load i8*, i8** %4, align 4
+- call void @"main.closureFunctionGoroutine$1"(i32 %2, i8* %5)
++ %1 = load i32, ptr %0, align 4
++ %2 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
++ %3 = load ptr, ptr %2, align 4
++ call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
+ ret void
+ }
+
+-declare void @runtime.printint32(i32, i8*) #0
++declare void @runtime.printint32(i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.funcGoroutine(i8* %fn.context, void ()* %fn.funcptr, i8*
%context) unnamed_addr #1 {
++define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context)
unnamed_addr #1 {
+ entry:
+- %0 = call i8* @runtime.alloc(i32 12, i8* null, i8* undef) #8
+- %1 = bitcast i8* %0 to i32*
+- store i32 5, i32* %1, align 4
+- %2 = getelementptr inbounds i8, i8* %0, i32 4
+- %3 = bitcast i8* %2 to i8**
+- store i8* %fn.context, i8** %3, align 4
+- %4 = getelementptr inbounds i8, i8* %0, i32 8
+- %5 = bitcast i8* %4 to void ()**
+- store void ()* %fn.funcptr, void ()** %5, align 4
+- %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(void (i8*)* @main.funcGoroutine.gowrapper to i32), i8* undef) #8
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@main.funcGoroutine.gowrapper to i32), i8* nonnull %0, i32 %stacksize, i8* undef) #8
++ %0 = call ptr @runtime.alloc(i32 12, ptr null, ptr undef) #8
++ store i32 5, ptr %0, align 4
++ %1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
++ store ptr %fn.context, ptr %1, align 4
++ %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
++ store ptr %fn.funcptr, ptr %2, align 4
++ %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #8
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @main.funcGoroutine.gowrapper(i8* %0) unnamed_addr #5 {
++define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #5 {
+ entry:
+- %1 = bitcast i8* %0 to i32*
+- %2 = load i32, i32* %1, align 4
+- %3 = getelementptr inbounds i8, i8* %0, i32 4
+- %4 = bitcast i8* %3 to i8**
+- %5 = load i8*, i8** %4, align 4
+- %6 = getelementptr inbounds i8, i8* %0, i32 8
+- %7 = bitcast i8* %6 to void (i32, i8*)**
+- %8 = load void (i32, i8*)*, void (i32, i8*)** %7, align 4
+- call void %8(i32 %2, i8* %5) #8
++ %1 = load i32, ptr %0, align 4
++ %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
++ %3 = load ptr, ptr %2, align 4
++ %4 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
++ %5 = load ptr, ptr %4, align 4
++ call void %5(i32 %1, ptr %3) #8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.recoverBuiltinGoroutine(i8* %context) unnamed_addr #1 {
++define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.copyBuiltinGoroutine(i8* %dst.data, i32 %dst.len, i32 %dst.cap,
i8* %src.data, i32 %src.len, i32 %src.cap, i8* %context) unnamed_addr #1 {
++define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap,
ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
+ entry:
+- %copy.n = call i32 @runtime.sliceCopy(i8* %dst.data, i8* %src.data, i32 %dst.len, i32
%src.len, i32 1, i8* undef) #8
++ %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32
%src.len, i32 1, ptr undef) #8
+ ret void
+ }
+
+-declare i32 @runtime.sliceCopy(i8* nocapture writeonly, i8* nocapture readonly, i32,
i32, i32, i8*) #0
++declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32,
i32, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.closeBuiltinGoroutine(%runtime.channel*
dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 {
++define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr
%context) unnamed_addr #1 {
+ entry:
+- call void @runtime.chanClose(%runtime.channel* %ch, i8* undef) #8
++ call void @runtime.chanClose(ptr %ch, ptr undef) #8
+ ret void
+ }
+
+-declare void @runtime.chanClose(%runtime.channel* dereferenceable_or_null(32), i8*) #0
++declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8*
%context) unnamed_addr #1 {
++define hidden void @main.startInterfaceMethod(i32 %itf.typecode, ptr %itf.value, ptr
%context) unnamed_addr #1 {
+ entry:
+- %0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef) #8
+- %1 = bitcast i8* %0 to i8**
+- store i8* %itf.value, i8** %1, align 4
+- %2 = getelementptr inbounds i8, i8* %0, i32 4
+- %.repack = bitcast i8* %2 to i8**
+- store i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"main$string", i32 0,
i32 0), i8** %.repack, align 4
+- %.repack1 = getelementptr inbounds i8, i8* %0, i32 8
+- %3 = bitcast i8* %.repack1 to i32*
+- store i32 4, i32* %3, align 4
+- %4 = getelementptr inbounds i8, i8* %0, i32 12
+- %5 = bitcast i8* %4 to i32*
+- store i32 %itf.typecode, i32* %5, align 4
+- %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(void (i8*)* @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"
to i32), i8* undef) #8
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), i8*
nonnull %0, i32 %stacksize, i8* undef) #8
++ %0 = call ptr @runtime.alloc(i32 16, ptr null, ptr undef) #8
++ store ptr %itf.value, ptr %0, align 4
++ %1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 1
++ store ptr @"main$string", ptr %1, align 4
++ %.repack1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32
1, i32 1
++ store i32 4, ptr %.repack1, align 4
++ %2 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 2
++ store i32 %itf.typecode, ptr %2, align 4
++ %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint
(ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32),
ptr undef) #8
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr
nonnull %0, i32 %stacksize, ptr undef) #8
+ ret void
+ }
+
+-declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8*, i8*,
i32, i32, i8*) #6
++declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr,
i32, i32, ptr) #6
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(i8* %0)
unnamed_addr #7 {
++define linkonce_odr void
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0)
unnamed_addr #7 {
+ entry:
+- %1 = bitcast i8* %0 to i8**
+- %2 = load i8*, i8** %1, align 4
+- %3 = getelementptr inbounds i8, i8* %0, i32 4
+- %4 = bitcast i8* %3 to i8**
+- %5 = load i8*, i8** %4, align 4
+- %6 = getelementptr inbounds i8, i8* %0, i32 8
+- %7 = bitcast i8* %6 to i32*
+- %8 = load i32, i32* %7, align 4
+- %9 = getelementptr inbounds i8, i8* %0, i32 12
+- %10 = bitcast i8* %9 to i32*
+- %11 = load i32, i32* %10, align 4
+- call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8* %2,
i8* %5, i32 %8, i32 %11, i8* undef) #8
++ %1 = load ptr, ptr %0, align 4
++ %2 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 1
++ %3 = load ptr, ptr %2, align 4
++ %4 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 2
++ %5 = load i32, ptr %4, align 4
++ %6 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 3
++ %7 = load i32, ptr %6, align 4
++ call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1,
ptr %3, i32 %5, i32 %7, ptr undef) #8
+ ret void
+ }
+
+diff --git a/compiler/testdata/goroutine-wasm-asyncify.ll
b/compiler/testdata/goroutine-wasm-asyncify.ll
+index 21da7477..280f216a 100644
+--- a/compiler/testdata/goroutine-wasm-asyncify.ll
++++ b/compiler/testdata/goroutine-wasm-asyncify.ll
+@@ -3,210 +3,184 @@ source_filename = "goroutine.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8*
}
+-%runtime.channelBlockedList = type { %runtime.channelBlockedList*,
%"internal/task.Task"*, %runtime.chanSelectState*, {
%runtime.channelBlockedList*, i32, i32 } }
+-%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64,
%"internal/task.gcData", %"internal/task.state", i8* }
+-%"internal/task.gcData" = type { i8* }
+-%"internal/task.state" = type { i32, i8*,
%"internal/task.stackState", i1 }
+-%"internal/task.stackState" = type { i32, i32 }
+-%runtime.chanSelectState = type { %runtime.channel*, i8* }
++%runtime._string = type { ptr, i32 }
+
+ @"main$string" = internal unnamed_addr constant [4 x i8] c"test",
align 1
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.regularFunctionGoroutine(i8* %context) unnamed_addr #1 {
++define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"main.regularFunction$gowrapper" to i32), i8* nonnull inttoptr (i32 5 to i8*),
i32 16384, i8* undef) #8
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr),
i32 16384, ptr undef) #8
+ ret void
+ }
+
+-declare void @main.regularFunction(i32, i8*) #0
++declare void @main.regularFunction(i32, ptr) #0
+
+-declare void @runtime.deadlock(i8*) #0
++declare void @runtime.deadlock(ptr) #0
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @"main.regularFunction$gowrapper"(i8* %0)
unnamed_addr #2 {
++define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0)
unnamed_addr #2 {
+ entry:
+- %unpack.int = ptrtoint i8* %0 to i32
+- call void @main.regularFunction(i32 %unpack.int, i8* undef) #8
+- call void @runtime.deadlock(i8* undef) #8
++ %unpack.int = ptrtoint ptr %0 to i32
++ call void @main.regularFunction(i32 %unpack.int, ptr undef) #8
++ call void @runtime.deadlock(ptr undef) #8
+ unreachable
+ }
+
+-declare void @"internal/task.start"(i32, i8*, i32, i8*) #0
++declare void @"internal/task.start"(i32, ptr, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.inlineFunctionGoroutine(i8* %context) unnamed_addr #1 {
++define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"main.inlineFunctionGoroutine$1$gowrapper" to i32), i8* nonnull inttoptr (i32 5
to i8*), i32 16384, i8* undef) #8
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5
to ptr), i32 16384, ptr undef) #8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context)
unnamed_addr #1 {
++define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context)
unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(i8* %0)
unnamed_addr #3 {
++define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(ptr %0)
unnamed_addr #3 {
+ entry:
+- %unpack.int = ptrtoint i8* %0 to i32
+- call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, i8* undef)
+- call void @runtime.deadlock(i8* undef) #8
++ %unpack.int = ptrtoint ptr %0 to i32
++ call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, ptr undef)
++ call void @runtime.deadlock(ptr undef) #8
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.closureFunctionGoroutine(i8* %context) unnamed_addr #1 {
+-entry:
+- %n = call i8* @runtime.alloc(i32 4, i8* nonnull inttoptr (i32 3 to i8*), i8* undef)
#8
+- %0 = bitcast i8* %n to i32*
+- call void @runtime.trackPointer(i8* nonnull %n, i8* undef) #8
+- store i32 3, i32* %0, align 4
+- call void @runtime.trackPointer(i8* nonnull %n, i8* undef) #8
+- call void @runtime.trackPointer(i8* bitcast (void (i32, i8*)*
@"main.closureFunctionGoroutine$1" to i8*), i8* undef) #8
+- %1 = call i8* @runtime.alloc(i32 8, i8* null, i8* undef) #8
+- call void @runtime.trackPointer(i8* nonnull %1, i8* undef) #8
+- %2 = bitcast i8* %1 to i32*
+- store i32 5, i32* %2, align 4
+- %3 = getelementptr inbounds i8, i8* %1, i32 4
+- %4 = bitcast i8* %3 to i8**
+- store i8* %n, i8** %4, align 4
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"main.closureFunctionGoroutine$1$gowrapper" to i32), i8* nonnull %1, i32 16384,
i8* undef) #8
+- %5 = load i32, i32* %0, align 4
+- call void @runtime.printint32(i32 %5, i8* undef) #8
++define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
++entry:
++ %n = call ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef)
#8
++ call void @runtime.trackPointer(ptr nonnull %n, ptr undef) #8
++ store i32 3, ptr %n, align 4
++ call void @runtime.trackPointer(ptr nonnull %n, ptr undef) #8
++ call void @runtime.trackPointer(ptr nonnull
@"main.closureFunctionGoroutine$1", ptr undef) #8
++ %0 = call ptr @runtime.alloc(i32 8, ptr null, ptr undef) #8
++ call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #8
++ store i32 5, ptr %0, align 4
++ %1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
++ store ptr %n, ptr %1, align 4
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 16384,
ptr undef) #8
++ %2 = load i32, ptr %n, align 4
++ call void @runtime.printint32(i32 %2, ptr undef) #8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define internal void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context)
unnamed_addr #1 {
++define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context)
unnamed_addr #1 {
+ entry:
+- %unpack.ptr = bitcast i8* %context to i32*
+- store i32 7, i32* %unpack.ptr, align 4
++ store i32 7, ptr %context, align 4
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(i8* %0)
unnamed_addr #4 {
++define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0)
unnamed_addr #4 {
+ entry:
+- %1 = bitcast i8* %0 to i32*
+- %2 = load i32, i32* %1, align 4
+- %3 = getelementptr inbounds i8, i8* %0, i32 4
+- %4 = bitcast i8* %3 to i8**
+- %5 = load i8*, i8** %4, align 4
+- call void @"main.closureFunctionGoroutine$1"(i32 %2, i8* %5)
+- call void @runtime.deadlock(i8* undef) #8
++ %1 = load i32, ptr %0, align 4
++ %2 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
++ %3 = load ptr, ptr %2, align 4
++ call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
++ call void @runtime.deadlock(ptr undef) #8
+ unreachable
+ }
+
+-declare void @runtime.printint32(i32, i8*) #0
++declare void @runtime.printint32(i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.funcGoroutine(i8* %fn.context, void ()* %fn.funcptr, i8*
%context) unnamed_addr #1 {
++define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context)
unnamed_addr #1 {
+ entry:
+- %0 = call i8* @runtime.alloc(i32 12, i8* null, i8* undef) #8
+- call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #8
+- %1 = bitcast i8* %0 to i32*
+- store i32 5, i32* %1, align 4
+- %2 = getelementptr inbounds i8, i8* %0, i32 4
+- %3 = bitcast i8* %2 to i8**
+- store i8* %fn.context, i8** %3, align 4
+- %4 = getelementptr inbounds i8, i8* %0, i32 8
+- %5 = bitcast i8* %4 to void ()**
+- store void ()* %fn.funcptr, void ()** %5, align 4
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@main.funcGoroutine.gowrapper to i32), i8* nonnull %0, i32 16384, i8* undef) #8
++ %0 = call ptr @runtime.alloc(i32 12, ptr null, ptr undef) #8
++ call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #8
++ store i32 5, ptr %0, align 4
++ %1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
++ store ptr %fn.context, ptr %1, align 4
++ %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
++ store ptr %fn.funcptr, ptr %2, align 4
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 16384, ptr undef) #8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void @main.funcGoroutine.gowrapper(i8* %0) unnamed_addr #5 {
++define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #5 {
+ entry:
+- %1 = bitcast i8* %0 to i32*
+- %2 = load i32, i32* %1, align 4
+- %3 = getelementptr inbounds i8, i8* %0, i32 4
+- %4 = bitcast i8* %3 to i8**
+- %5 = load i8*, i8** %4, align 4
+- %6 = getelementptr inbounds i8, i8* %0, i32 8
+- %7 = bitcast i8* %6 to void (i32, i8*)**
+- %8 = load void (i32, i8*)*, void (i32, i8*)** %7, align 4
+- call void %8(i32 %2, i8* %5) #8
+- call void @runtime.deadlock(i8* undef) #8
++ %1 = load i32, ptr %0, align 4
++ %2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
++ %3 = load ptr, ptr %2, align 4
++ %4 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
++ %5 = load ptr, ptr %4, align 4
++ call void %5(i32 %1, ptr %3) #8
++ call void @runtime.deadlock(ptr undef) #8
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.recoverBuiltinGoroutine(i8* %context) unnamed_addr #1 {
++define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.copyBuiltinGoroutine(i8* %dst.data, i32 %dst.len, i32 %dst.cap,
i8* %src.data, i32 %src.len, i32 %src.cap, i8* %context) unnamed_addr #1 {
++define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap,
ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
+ entry:
+- %copy.n = call i32 @runtime.sliceCopy(i8* %dst.data, i8* %src.data, i32 %dst.len, i32
%src.len, i32 1, i8* undef) #8
++ %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32
%src.len, i32 1, ptr undef) #8
+ ret void
+ }
+
+-declare i32 @runtime.sliceCopy(i8* nocapture writeonly, i8* nocapture readonly, i32,
i32, i32, i8*) #0
++declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32,
i32, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.closeBuiltinGoroutine(%runtime.channel*
dereferenceable_or_null(32) %ch, i8* %context) unnamed_addr #1 {
++define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr
%context) unnamed_addr #1 {
+ entry:
+- call void @runtime.chanClose(%runtime.channel* %ch, i8* undef) #8
++ call void @runtime.chanClose(ptr %ch, ptr undef) #8
+ ret void
+ }
+
+-declare void @runtime.chanClose(%runtime.channel* dereferenceable_or_null(32), i8*) #0
++declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.startInterfaceMethod(i32 %itf.typecode, i8* %itf.value, i8*
%context) unnamed_addr #1 {
++define hidden void @main.startInterfaceMethod(i32 %itf.typecode, ptr %itf.value, ptr
%context) unnamed_addr #1 {
+ entry:
+- %0 = call i8* @runtime.alloc(i32 16, i8* null, i8* undef) #8
+- call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #8
+- %1 = bitcast i8* %0 to i8**
+- store i8* %itf.value, i8** %1, align 4
+- %2 = getelementptr inbounds i8, i8* %0, i32 4
+- %.repack = bitcast i8* %2 to i8**
+- store i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"main$string", i32 0,
i32 0), i8** %.repack, align 4
+- %.repack1 = getelementptr inbounds i8, i8* %0, i32 8
+- %3 = bitcast i8* %.repack1 to i32*
+- store i32 4, i32* %3, align 4
+- %4 = getelementptr inbounds i8, i8* %0, i32 12
+- %5 = bitcast i8* %4 to i32*
+- store i32 %itf.typecode, i32* %5, align 4
+- call void @"internal/task.start"(i32 ptrtoint (void (i8*)*
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), i8*
nonnull %0, i32 16384, i8* undef) #8
++ %0 = call ptr @runtime.alloc(i32 16, ptr null, ptr undef) #8
++ call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #8
++ store ptr %itf.value, ptr %0, align 4
++ %1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 1
++ store ptr @"main$string", ptr %1, align 4
++ %.repack1 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32
1, i32 1
++ store i32 4, ptr %.repack1, align 4
++ %2 = getelementptr inbounds { ptr, %runtime._string, i32 }, ptr %0, i32 0, i32 2
++ store i32 %itf.typecode, ptr %2, align 4
++ call void @"internal/task.start"(i32 ptrtoint (ptr
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr
nonnull %0, i32 16384, ptr undef) #8
+ ret void
+ }
+
+-declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8*, i8*,
i32, i32, i8*) #6
++declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr,
i32, i32, ptr) #6
+
+ ; Function Attrs: nounwind
+-define linkonce_odr void
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(i8* %0)
unnamed_addr #7 {
++define linkonce_odr void
@"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0)
unnamed_addr #7 {
+ entry:
+- %1 = bitcast i8* %0 to i8**
+- %2 = load i8*, i8** %1, align 4
+- %3 = getelementptr inbounds i8, i8* %0, i32 4
+- %4 = bitcast i8* %3 to i8**
+- %5 = load i8*, i8** %4, align 4
+- %6 = getelementptr inbounds i8, i8* %0, i32 8
+- %7 = bitcast i8* %6 to i32*
+- %8 = load i32, i32* %7, align 4
+- %9 = getelementptr inbounds i8, i8* %0, i32 12
+- %10 = bitcast i8* %9 to i32*
+- %11 = load i32, i32* %10, align 4
+- call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(i8* %2,
i8* %5, i32 %8, i32 %11, i8* undef) #8
+- call void @runtime.deadlock(i8* undef) #8
++ %1 = load ptr, ptr %0, align 4
++ %2 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 1
++ %3 = load ptr, ptr %2, align 4
++ %4 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 2
++ %5 = load i32, ptr %4, align 4
++ %6 = getelementptr inbounds { ptr, ptr, i32, i32 }, ptr %0, i32 0, i32 3
++ %7 = load i32, ptr %6, align 4
++ call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1,
ptr %3, i32 %5, i32 %7, ptr undef) #8
++ call void @runtime.deadlock(ptr undef) #8
+ unreachable
+ }
+
+diff --git a/compiler/testdata/interface.ll b/compiler/testdata/interface.ll
+index 0b44585a..38d4e567 100644
+--- a/compiler/testdata/interface.ll
++++ b/compiler/testdata/interface.ll
+@@ -3,71 +3,70 @@ source_filename = "interface.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*,
%runtime.typecodeID*, i32 }
+-%runtime.interfaceMethodInfo = type { i8*, i32 }
+-%runtime._interface = type { i32, i8* }
+-%runtime._string = type { i8*, i32 }
+-
+-@"reflect/types.type:basic:int" = linkonce_odr constant %runtime.typecodeID {
%runtime.typecodeID* null, i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID*
@"reflect/types.type:pointer:basic:int", i32 0 }
+-@"reflect/types.type:pointer:basic:int" = linkonce_odr constant
%runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:int", i32
0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 }
+-@"reflect/types.type:pointer:named:error" = linkonce_odr constant
%runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:named:error",
i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 }
+-@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID
{ %runtime.typecodeID*
@"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0,
%runtime.interfaceMethodInfo* null, %runtime.typecodeID*
@"reflect/types.type:pointer:named:error", i32 ptrtoint (i1 (i32)*
@"interface:{Error:func:{}{basic:string}}.$typeassert" to i32) }
+-@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr
constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]*
@"reflect/types.interface:interface{Error() string}$interface" to
%runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID*
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}", i32
ptrtoint (i1 (i32)* @"interface:{Error:func:{}{basic:string}}.$typeassert" to
i32) }
++%runtime.typecodeID = type { ptr, i32, ptr, ptr, i32 }
++%runtime._interface = type { i32, ptr }
++%runtime._string = type { ptr, i32 }
++
++@"reflect/types.type:basic:int" = linkonce_odr constant %runtime.typecodeID {
ptr null, i32 0, ptr null, ptr @"reflect/types.type:pointer:basic:int", i32 0 }
++@"reflect/types.type:pointer:basic:int" = linkonce_odr constant
%runtime.typecodeID { ptr @"reflect/types.type:basic:int", i32 0, ptr null, ptr
null, i32 0 }
++@"reflect/types.type:pointer:named:error" = linkonce_odr constant
%runtime.typecodeID { ptr @"reflect/types.type:named:error", i32 0, ptr null,
ptr null, i32 0 }
++@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID
{ ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, ptr
null, ptr @"reflect/types.type:pointer:named:error", i32 ptrtoint (ptr
@"interface:{Error:func:{}{basic:string}}.$typeassert" to i32) }
++@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr
constant %runtime.typecodeID { ptr @"reflect/types.interface:interface{Error()
string}$interface", i32 0, ptr null, ptr
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}", i32
ptrtoint (ptr @"interface:{Error:func:{}{basic:string}}.$typeassert" to i32) }
+ @"reflect/methods.Error() string" = linkonce_odr constant i8 0, align 1
+-@"reflect/types.interface:interface{Error() string}$interface" = linkonce_odr
constant [1 x i8*] [i8* @"reflect/methods.Error() string"]
+-@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" =
linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID*
@"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0,
%runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 }
+-@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" =
linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID*
@"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0,
%runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 }
+-@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr
constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]*
@"reflect/types.interface:interface{String() string}$interface" to
%runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID*
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", i32
ptrtoint (i1 (i32)* @"interface:{String:func:{}{basic:string}}.$typeassert" to
i32) }
++@"reflect/types.interface:interface{Error() string}$interface" = linkonce_odr
constant [1 x ptr] [ptr @"reflect/methods.Error() string"]
++@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" =
linkonce_odr constant %runtime.typecodeID { ptr
@"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, ptr null,
ptr null, i32 0 }
++@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" =
linkonce_odr constant %runtime.typecodeID { ptr
@"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0, ptr null,
ptr null, i32 0 }
++@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr
constant %runtime.typecodeID { ptr @"reflect/types.interface:interface{String()
string}$interface", i32 0, ptr null, ptr
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", i32
ptrtoint (ptr @"interface:{String:func:{}{basic:string}}.$typeassert" to i32) }
+ @"reflect/methods.String() string" = linkonce_odr constant i8 0, align 1
+-@"reflect/types.interface:interface{String() string}$interface" = linkonce_odr
constant [1 x i8*] [i8* @"reflect/methods.String() string"]
++@"reflect/types.interface:interface{String() string}$interface" = linkonce_odr
constant [1 x ptr] [ptr @"reflect/methods.String() string"]
+ @"reflect/types.typeid:basic:int" = external constant i8
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._interface @main.simpleType(i8* %context) unnamed_addr #1 {
++define hidden %runtime._interface @main.simpleType(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.trackPointer(i8* null, i8* undef) #6
+- ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID*
@"reflect/types.type:basic:int" to i32), i8* null }
++ call void @runtime.trackPointer(ptr null, ptr undef) #6
++ ret %runtime._interface { i32 ptrtoint (ptr @"reflect/types.type:basic:int"
to i32), ptr null }
+ }
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._interface @main.pointerType(i8* %context) unnamed_addr #1 {
++define hidden %runtime._interface @main.pointerType(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.trackPointer(i8* null, i8* undef) #6
+- ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID*
@"reflect/types.type:pointer:basic:int" to i32), i8* null }
++ call void @runtime.trackPointer(ptr null, ptr undef) #6
++ ret %runtime._interface { i32 ptrtoint (ptr
@"reflect/types.type:pointer:basic:int" to i32), ptr null }
+ }
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._interface @main.interfaceType(i8* %context) unnamed_addr #1 {
++define hidden %runtime._interface @main.interfaceType(ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.trackPointer(i8* null, i8* undef) #6
+- ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID*
@"reflect/types.type:pointer:named:error" to i32), i8* null }
++ call void @runtime.trackPointer(ptr null, ptr undef) #6
++ ret %runtime._interface { i32 ptrtoint (ptr
@"reflect/types.type:pointer:named:error" to i32), ptr null }
+ }
+
+ declare i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(i32) #2
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._interface @main.anonymousInterfaceType(i8* %context)
unnamed_addr #1 {
++define hidden %runtime._interface @main.anonymousInterfaceType(ptr %context)
unnamed_addr #1 {
+ entry:
+- call void @runtime.trackPointer(i8* null, i8* undef) #6
+- ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID*
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" to i32),
i8* null }
++ call void @runtime.trackPointer(ptr null, ptr undef) #6
++ ret %runtime._interface { i32 ptrtoint (ptr
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" to i32),
ptr null }
+ }
+
+ declare i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(i32) #3
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.isInt(i32 %itf.typecode, i8* %itf.value, i8* %context)
unnamed_addr #1 {
++define hidden i1 @main.isInt(i32 %itf.typecode, ptr %itf.value, ptr %context)
unnamed_addr #1 {
+ entry:
+- %typecode = call i1 @runtime.typeAssert(i32 %itf.typecode, i8* nonnull
@"reflect/types.typeid:basic:int", i8* undef) #6
++ %typecode = call i1 @runtime.typeAssert(i32 %itf.typecode, ptr nonnull
@"reflect/types.typeid:basic:int", ptr undef) #6
+ br i1 %typecode, label %typeassert.ok, label %typeassert.next
+
+ typeassert.next: ; preds = %typeassert.ok, %entry
+@@ -77,10 +76,10 @@ typeassert.ok: ; preds = %entry
+ br label %typeassert.next
+ }
+
+-declare i1 @runtime.typeAssert(i32, i8* dereferenceable_or_null(1), i8*) #0
++declare i1 @runtime.typeAssert(i32, ptr dereferenceable_or_null(1), ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.isError(i32 %itf.typecode, i8* %itf.value, i8* %context)
unnamed_addr #1 {
++define hidden i1 @main.isError(i32 %itf.typecode, ptr %itf.value, ptr %context)
unnamed_addr #1 {
+ entry:
+ %0 = call i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(i32
%itf.typecode) #6
+ br i1 %0, label %typeassert.ok, label %typeassert.next
+@@ -93,7 +92,7 @@ typeassert.ok: ; preds = %entry
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.isStringer(i32 %itf.typecode, i8* %itf.value, i8* %context)
unnamed_addr #1 {
++define hidden i1 @main.isStringer(i32 %itf.typecode, ptr %itf.value, ptr %context)
unnamed_addr #1 {
+ entry:
+ %0 = call i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(i32
%itf.typecode) #6
+ br i1 %0, label %typeassert.ok, label %typeassert.next
+@@ -106,24 +105,24 @@ typeassert.ok: ; preds = %entry
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8 @main.callFooMethod(i32 %itf.typecode, i8* %itf.value, i8* %context)
unnamed_addr #1 {
++define hidden i8 @main.callFooMethod(i32 %itf.typecode, ptr %itf.value, ptr %context)
unnamed_addr #1 {
+ entry:
+- %0 = call i8
@"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(i8*
%itf.value, i32 3, i32 %itf.typecode, i8* undef) #6
++ %0 = call i8
@"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr
%itf.value, i32 3, i32 %itf.typecode, ptr undef) #6
+ ret i8 %0
+ }
+
+-declare i8
@"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(i8*,
i32, i32, i8*) #4
++declare i8
@"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr,
i32, i32, ptr) #4
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._string @main.callErrorMethod(i32 %itf.typecode, i8* %itf.value,
i8* %context) unnamed_addr #1 {
++define hidden %runtime._string @main.callErrorMethod(i32 %itf.typecode, ptr %itf.value,
ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = call %runtime._string
@"interface:{Error:func:{}{basic:string}}.Error$invoke"(i8* %itf.value, i32
%itf.typecode, i8* undef) #6
++ %0 = call %runtime._string
@"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr %itf.value, i32
%itf.typecode, ptr undef) #6
+ %1 = extractvalue %runtime._string %0, 0
+- call void @runtime.trackPointer(i8* %1, i8* undef) #6
++ call void @runtime.trackPointer(ptr %1, ptr undef) #6
+ ret %runtime._string %0
+ }
+
+-declare %runtime._string
@"interface:{Error:func:{}{basic:string}}.Error$invoke"(i8*, i32, i8*) #5
++declare %runtime._string
@"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr, i32, ptr) #5
+
+ attributes #0 = {
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+ attributes #1 = { nounwind
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+diff --git a/compiler/testdata/pointer.ll b/compiler/testdata/pointer.ll
+index cedea380..9bc8bd35 100644
+--- a/compiler/testdata/pointer.ll
++++ b/compiler/testdata/pointer.ll
+@@ -3,76 +3,72 @@ source_filename = "pointer.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden [0 x i32] @main.pointerDerefZero([0 x i32]* %x, i8* %context) unnamed_addr
#1 {
++define hidden [0 x i32] @main.pointerDerefZero(ptr %x, ptr %context) unnamed_addr #1 {
+ entry:
+ ret [0 x i32] zeroinitializer
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32* @main.pointerCastFromUnsafe(i8* %x, i8* %context) unnamed_addr #1 {
++define hidden ptr @main.pointerCastFromUnsafe(ptr %x, ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = bitcast i8* %x to i32*
+- call void @runtime.trackPointer(i8* %x, i8* undef) #2
+- ret i32* %0
++ call void @runtime.trackPointer(ptr %x, ptr undef) #2
++ ret ptr %x
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8* @main.pointerCastToUnsafe(i32* dereferenceable_or_null(4) %x, i8*
%context) unnamed_addr #1 {
++define hidden ptr @main.pointerCastToUnsafe(ptr dereferenceable_or_null(4) %x, ptr
%context) unnamed_addr #1 {
+ entry:
+- %0 = bitcast i32* %x to i8*
+- call void @runtime.trackPointer(i8* %0, i8* undef) #2
+- ret i8* %0
++ call void @runtime.trackPointer(ptr %x, ptr undef) #2
++ ret ptr %x
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8* @main.pointerCastToUnsafeNoop(i8* dereferenceable_or_null(1) %x, i8*
%context) unnamed_addr #1 {
++define hidden ptr @main.pointerCastToUnsafeNoop(ptr dereferenceable_or_null(1) %x, ptr
%context) unnamed_addr #1 {
+ entry:
+- call void @runtime.trackPointer(i8* %x, i8* undef) #2
+- ret i8* %x
++ call void @runtime.trackPointer(ptr %x, ptr undef) #2
++ ret ptr %x
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8* @main.pointerUnsafeGEPFixedOffset(i8* dereferenceable_or_null(1) %ptr,
i8* %context) unnamed_addr #1 {
++define hidden ptr @main.pointerUnsafeGEPFixedOffset(ptr dereferenceable_or_null(1) %ptr,
ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.trackPointer(i8* %ptr, i8* undef) #2
+- %0 = getelementptr inbounds i8, i8* %ptr, i32 10
+- call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2
+- call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2
+- ret i8* %0
++ call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
++ %0 = getelementptr inbounds i8, ptr %ptr, i32 10
++ call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
++ call void @runtime.trackPointer(ptr nonnull %0, ptr undef) #2
++ ret ptr %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8* @main.pointerUnsafeGEPByteOffset(i8* dereferenceable_or_null(1) %ptr,
i32 %offset, i8* %context) unnamed_addr #1 {
++define hidden ptr @main.pointerUnsafeGEPByteOffset(ptr dereferenceable_or_null(1) %ptr,
i32 %offset, ptr %context) unnamed_addr #1 {
+ entry:
+- call void @runtime.trackPointer(i8* %ptr, i8* undef) #2
+- %0 = getelementptr inbounds i8, i8* %ptr, i32 %offset
+- call void @runtime.trackPointer(i8* %0, i8* undef) #2
+- call void @runtime.trackPointer(i8* %0, i8* undef) #2
+- ret i8* %0
++ call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
++ %0 = getelementptr inbounds i8, ptr %ptr, i32 %offset
++ call void @runtime.trackPointer(ptr %0, ptr undef) #2
++ call void @runtime.trackPointer(ptr %0, ptr undef) #2
++ ret ptr %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32* @main.pointerUnsafeGEPIntOffset(i32* dereferenceable_or_null(4) %ptr,
i32 %offset, i8* %context) unnamed_addr #1 {
++define hidden ptr @main.pointerUnsafeGEPIntOffset(ptr dereferenceable_or_null(4) %ptr,
i32 %offset, ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = bitcast i32* %ptr to i8*
+- call void @runtime.trackPointer(i8* %0, i8* undef) #2
+- %1 = getelementptr i32, i32* %ptr, i32 %offset
+- %2 = bitcast i32* %1 to i8*
+- call void @runtime.trackPointer(i8* %2, i8* undef) #2
+- %3 = bitcast i32* %1 to i8*
+- call void @runtime.trackPointer(i8* %3, i8* undef) #2
+- ret i32* %1
++ call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
++ %0 = shl i32 %offset, 2
++ %1 = getelementptr inbounds i8, ptr %ptr, i32 %0
++ call void @runtime.trackPointer(ptr %1, ptr undef) #2
++ call void @runtime.trackPointer(ptr %1, ptr undef) #2
++ ret ptr %1
+ }
+
+ attributes #0 = {
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+diff --git a/compiler/testdata/pragma.ll b/compiler/testdata/pragma.ll
+index b243602d..c49c83bd 100644
+--- a/compiler/testdata/pragma.ll
++++ b/compiler/testdata/pragma.ll
+@@ -10,12 +10,12 @@ target triple = "wasm32-unknown-wasi"
+ @undefinedGlobalNotInSection = external global i32, align 4
+ @main.multipleGlobalPragmas = hidden global i32 0, section ".global_section",
align 1024
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+@@ -27,27 +27,27 @@ entry:
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @somepkg.someFunction1(i8* %context) unnamed_addr #1 {
++define hidden void @somepkg.someFunction1(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+-declare void @somepkg.someFunction2(i8*) #0
++declare void @somepkg.someFunction2(ptr) #0
+
+ ; Function Attrs: inlinehint nounwind
+-define hidden void @main.inlineFunc(i8* %context) unnamed_addr #3 {
++define hidden void @main.inlineFunc(ptr %context) unnamed_addr #3 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: noinline nounwind
+-define hidden void @main.noinlineFunc(i8* %context) unnamed_addr #4 {
++define hidden void @main.noinlineFunc(ptr %context) unnamed_addr #4 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden void @main.functionInSection(i8* %context) unnamed_addr #1 section
".special_function_section" {
++define hidden void @main.functionInSection(ptr %context) unnamed_addr #1 section
".special_function_section" {
+ entry:
+ ret void
+ }
+@@ -58,7 +58,7 @@ entry:
+ ret void
+ }
+
+-declare void @main.undefinedFunctionNotInSection(i8*) #0
++declare void @main.undefinedFunctionNotInSection(ptr) #0
+
+ attributes #0 = {
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+ attributes #1 = { nounwind
"target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
+diff --git a/compiler/testdata/slice.ll b/compiler/testdata/slice.ll
+index c2e3ebd9..56e40f5f 100644
+--- a/compiler/testdata/slice.ll
++++ b/compiler/testdata/slice.ll
+@@ -3,286 +3,270 @@ source_filename = "slice.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.sliceLen(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8*
%context) unnamed_addr #1 {
++define hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr
%context) unnamed_addr #1 {
+ entry:
+ ret i32 %ints.len
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.sliceCap(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i8*
%context) unnamed_addr #1 {
++define hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr
%context) unnamed_addr #1 {
+ entry:
+ ret i32 %ints.cap
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.sliceElement(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i32
%index, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32
%index, ptr %context) unnamed_addr #1 {
+ entry:
+ %.not = icmp ult i32 %index, %ints.len
+ br i1 %.not, label %lookup.next, label %lookup.throw
+
+ lookup.next: ; preds = %entry
+- %0 = getelementptr inbounds i32, i32* %ints.data, i32 %index
+- %1 = load i32, i32* %0, align 4
++ %0 = getelementptr inbounds i32, ptr %ints.data, i32 %index
++ %1 = load i32, ptr %0, align 4
+ ret i32 %1
+
+ lookup.throw: ; preds = %entry
+- call void @runtime.lookupPanic(i8* undef) #2
++ call void @runtime.lookupPanic(ptr undef) #2
+ unreachable
+ }
+
+-declare void @runtime.lookupPanic(i8*) #0
++declare void @runtime.lookupPanic(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden { i32*, i32, i32 } @main.sliceAppendValues(i32* %ints.data, i32 %ints.len,
i32 %ints.cap, i8* %context) unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len,
i32 %ints.cap, ptr %context) unnamed_addr #1 {
+ entry:
+- %varargs = call i8* @runtime.alloc(i32 12, i8* nonnull inttoptr (i32 3 to i8*), i8*
undef) #2
+- call void @runtime.trackPointer(i8* nonnull %varargs, i8* undef) #2
+- %0 = bitcast i8* %varargs to i32*
+- store i32 1, i32* %0, align 4
+- %1 = getelementptr inbounds i8, i8* %varargs, i32 4
+- %2 = bitcast i8* %1 to i32*
+- store i32 2, i32* %2, align 4
+- %3 = getelementptr inbounds i8, i8* %varargs, i32 8
+- %4 = bitcast i8* %3 to i32*
+- store i32 3, i32* %4, align 4
+- %append.srcPtr = bitcast i32* %ints.data to i8*
+- %append.new = call { i8*, i32, i32 } @runtime.sliceAppend(i8* %append.srcPtr, i8*
nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, i8* undef) #2
+- %append.newPtr = extractvalue { i8*, i32, i32 } %append.new, 0
+- %append.newBuf = bitcast i8* %append.newPtr to i32*
+- %append.newLen = extractvalue { i8*, i32, i32 } %append.new, 1
+- %append.newCap = extractvalue { i8*, i32, i32 } %append.new, 2
+- %5 = insertvalue { i32*, i32, i32 } undef, i32* %append.newBuf, 0
+- %6 = insertvalue { i32*, i32, i32 } %5, i32 %append.newLen, 1
+- %7 = insertvalue { i32*, i32, i32 } %6, i32 %append.newCap, 2
+- call void @runtime.trackPointer(i8* %append.newPtr, i8* undef) #2
+- ret { i32*, i32, i32 } %7
++ %varargs = call ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr
undef) #2
++ call void @runtime.trackPointer(ptr nonnull %varargs, ptr undef) #2
++ store i32 1, ptr %varargs, align 4
++ %0 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 1
++ store i32 2, ptr %0, align 4
++ %1 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 2
++ store i32 3, ptr %1, align 4
++ %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull
%varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr undef) #2
++ %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
++ %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
++ %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
++ %2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
++ %3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1
++ %4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2
++ call void @runtime.trackPointer(ptr %append.newPtr, ptr undef) #2
++ ret { ptr, i32, i32 } %4
+ }
+
+-declare { i8*, i32, i32 } @runtime.sliceAppend(i8*, i8* nocapture readonly, i32, i32,
i32, i32, i8*) #0
++declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32,
i32, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden { i32*, i32, i32 } @main.sliceAppendSlice(i32* %ints.data, i32 %ints.len,
i32 %ints.cap, i32* %added.data, i32 %added.len, i32 %added.cap, i8* %context)
unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len,
i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr
#1 {
+ entry:
+- %append.srcPtr = bitcast i32* %ints.data to i8*
+- %append.srcPtr1 = bitcast i32* %added.data to i8*
+- %append.new = call { i8*, i32, i32 } @runtime.sliceAppend(i8* %append.srcPtr, i8*
%append.srcPtr1, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, i8* undef) #2
+- %append.newPtr = extractvalue { i8*, i32, i32 } %append.new, 0
+- %append.newBuf = bitcast i8* %append.newPtr to i32*
+- %append.newLen = extractvalue { i8*, i32, i32 } %append.new, 1
+- %append.newCap = extractvalue { i8*, i32, i32 } %append.new, 2
+- %0 = insertvalue { i32*, i32, i32 } undef, i32* %append.newBuf, 0
+- %1 = insertvalue { i32*, i32, i32 } %0, i32 %append.newLen, 1
+- %2 = insertvalue { i32*, i32, i32 } %1, i32 %append.newCap, 2
+- call void @runtime.trackPointer(i8* %append.newPtr, i8* undef) #2
+- ret { i32*, i32, i32 } %2
++ %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr
%added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr undef) #2
++ %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
++ %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
++ %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
++ %0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
++ %1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1
++ %2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2
++ call void @runtime.trackPointer(ptr %append.newPtr, ptr undef) #2
++ ret { ptr, i32, i32 } %2
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.sliceCopy(i32* %dst.data, i32 %dst.len, i32 %dst.cap, i32*
%src.data, i32 %src.len, i32 %src.cap, i8* %context) unnamed_addr #1 {
++define hidden i32 @main.sliceCopy(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr
%src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
+ entry:
+- %copy.dstPtr = bitcast i32* %dst.data to i8*
+- %copy.srcPtr = bitcast i32* %src.data to i8*
+- %copy.n = call i32 @runtime.sliceCopy(i8* %copy.dstPtr, i8* %copy.srcPtr, i32
%dst.len, i32 %src.len, i32 4, i8* undef) #2
++ %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32
%src.len, i32 4, ptr undef) #2
+ ret i32 %copy.n
+ }
+
+-declare i32 @runtime.sliceCopy(i8* nocapture writeonly, i8* nocapture readonly, i32,
i32, i32, i8*) #0
++declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32,
i32, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden { i8*, i32, i32 } @main.makeByteSlice(i32 %len, i8* %context) unnamed_addr
#1 {
++define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr
#1 {
+ entry:
+ %slice.maxcap = icmp slt i32 %len, 0
+ br i1 %slice.maxcap, label %slice.throw, label %slice.next
+
+ slice.next: ; preds = %entry
+- %makeslice.buf = call i8* @runtime.alloc(i32 %len, i8* nonnull inttoptr (i32 3 to
i8*), i8* undef) #2
+- %0 = insertvalue { i8*, i32, i32 } undef, i8* %makeslice.buf, 0
+- %1 = insertvalue { i8*, i32, i32 } %0, i32 %len, 1
+- %2 = insertvalue { i8*, i32, i32 } %1, i32 %len, 2
+- call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2
+- ret { i8*, i32, i32 } %2
++ %makeslice.buf = call ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to
ptr), ptr undef) #2
++ %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
++ %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
++ %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
++ call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
++ ret { ptr, i32, i32 } %2
+
+ slice.throw: ; preds = %entry
+- call void @runtime.slicePanic(i8* undef) #2
++ call void @runtime.slicePanic(ptr undef) #2
+ unreachable
+ }
+
+-declare void @runtime.slicePanic(i8*) #0
++declare void @runtime.slicePanic(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden { i16*, i32, i32 } @main.makeInt16Slice(i32 %len, i8* %context)
unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.makeInt16Slice(i32 %len, ptr %context)
unnamed_addr #1 {
+ entry:
+ %slice.maxcap = icmp slt i32 %len, 0
+ br i1 %slice.maxcap, label %slice.throw, label %slice.next
+
+ slice.next: ; preds = %entry
+ %makeslice.cap = shl i32 %len, 1
+- %makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* nonnull inttoptr (i32
3 to i8*), i8* undef) #2
+- %makeslice.array = bitcast i8* %makeslice.buf to i16*
+- %0 = insertvalue { i16*, i32, i32 } undef, i16* %makeslice.array, 0
+- %1 = insertvalue { i16*, i32, i32 } %0, i32 %len, 1
+- %2 = insertvalue { i16*, i32, i32 } %1, i32 %len, 2
+- call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2
+- ret { i16*, i32, i32 } %2
++ %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32
3 to ptr), ptr undef) #2
++ %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
++ %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
++ %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
++ call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
++ ret { ptr, i32, i32 } %2
+
+ slice.throw: ; preds = %entry
+- call void @runtime.slicePanic(i8* undef) #2
++ call void @runtime.slicePanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { [3 x i8]*, i32, i32 } @main.makeArraySlice(i32 %len, i8* %context)
unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.makeArraySlice(i32 %len, ptr %context)
unnamed_addr #1 {
+ entry:
+ %slice.maxcap = icmp ugt i32 %len, 1431655765
+ br i1 %slice.maxcap, label %slice.throw, label %slice.next
+
+ slice.next: ; preds = %entry
+ %makeslice.cap = mul i32 %len, 3
+- %makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* nonnull inttoptr (i32
3 to i8*), i8* undef) #2
+- %makeslice.array = bitcast i8* %makeslice.buf to [3 x i8]*
+- %0 = insertvalue { [3 x i8]*, i32, i32 } undef, [3 x i8]* %makeslice.array, 0
+- %1 = insertvalue { [3 x i8]*, i32, i32 } %0, i32 %len, 1
+- %2 = insertvalue { [3 x i8]*, i32, i32 } %1, i32 %len, 2
+- call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2
+- ret { [3 x i8]*, i32, i32 } %2
++ %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32
3 to ptr), ptr undef) #2
++ %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
++ %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
++ %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
++ call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
++ ret { ptr, i32, i32 } %2
+
+ slice.throw: ; preds = %entry
+- call void @runtime.slicePanic(i8* undef) #2
++ call void @runtime.slicePanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { i32*, i32, i32 } @main.makeInt32Slice(i32 %len, i8* %context)
unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.makeInt32Slice(i32 %len, ptr %context)
unnamed_addr #1 {
+ entry:
+ %slice.maxcap = icmp ugt i32 %len, 1073741823
+ br i1 %slice.maxcap, label %slice.throw, label %slice.next
+
+ slice.next: ; preds = %entry
+ %makeslice.cap = shl i32 %len, 2
+- %makeslice.buf = call i8* @runtime.alloc(i32 %makeslice.cap, i8* nonnull inttoptr (i32
3 to i8*), i8* undef) #2
+- %makeslice.array = bitcast i8* %makeslice.buf to i32*
+- %0 = insertvalue { i32*, i32, i32 } undef, i32* %makeslice.array, 0
+- %1 = insertvalue { i32*, i32, i32 } %0, i32 %len, 1
+- %2 = insertvalue { i32*, i32, i32 } %1, i32 %len, 2
+- call void @runtime.trackPointer(i8* nonnull %makeslice.buf, i8* undef) #2
+- ret { i32*, i32, i32 } %2
++ %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32
3 to ptr), ptr undef) #2
++ %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
++ %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
++ %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
++ call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr undef) #2
++ ret { ptr, i32, i32 } %2
+
+ slice.throw: ; preds = %entry
+- call void @runtime.slicePanic(i8* undef) #2
++ call void @runtime.slicePanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8* @main.Add32(i8* %p, i32 %len, i8* %context) unnamed_addr #1 {
++define hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = getelementptr i8, i8* %p, i32 %len
+- call void @runtime.trackPointer(i8* %0, i8* undef) #2
+- ret i8* %0
++ %0 = getelementptr i8, ptr %p, i32 %len
++ call void @runtime.trackPointer(ptr %0, ptr undef) #2
++ ret ptr %0
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8* @main.Add64(i8* %p, i64 %len, i8* %context) unnamed_addr #1 {
++define hidden ptr @main.Add64(ptr %p, i64 %len, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = trunc i64 %len to i32
+- %1 = getelementptr i8, i8* %p, i32 %0
+- call void @runtime.trackPointer(i8* %1, i8* undef) #2
+- ret i8* %1
++ %1 = getelementptr i8, ptr %p, i32 %0
++ call void @runtime.trackPointer(ptr %1, ptr undef) #2
++ ret ptr %1
+ }
+
+ ; Function Attrs: nounwind
+-define hidden [4 x i32]* @main.SliceToArray(i32* %s.data, i32 %s.len, i32 %s.cap, i8*
%context) unnamed_addr #1 {
++define hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context)
unnamed_addr #1 {
+ entry:
+ %0 = icmp ult i32 %s.len, 4
+ br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
+
+ slicetoarray.next: ; preds = %entry
+- %1 = bitcast i32* %s.data to [4 x i32]*
+- ret [4 x i32]* %1
++ ret ptr %s.data
+
+ slicetoarray.throw: ; preds = %entry
+- call void @runtime.sliceToArrayPointerPanic(i8* undef) #2
++ call void @runtime.sliceToArrayPointerPanic(ptr undef) #2
+ unreachable
+ }
+
+-declare void @runtime.sliceToArrayPointerPanic(i8*) #0
++declare void @runtime.sliceToArrayPointerPanic(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context) unnamed_addr #1 {
++define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #1 {
+ entry:
+- %makeslice = call i8* @runtime.alloc(i32 24, i8* nonnull inttoptr (i32 3 to i8*), i8*
undef) #2
+- call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2
++ %makeslice = call ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr
undef) #2
++ call void @runtime.trackPointer(ptr nonnull %makeslice, ptr undef) #2
+ br i1 false, label %slicetoarray.throw, label %slicetoarray.next
+
+ slicetoarray.next: ; preds = %entry
+- %0 = bitcast i8* %makeslice to [4 x i32]*
+- ret [4 x i32]* %0
++ ret ptr %makeslice
+
+ slicetoarray.throw: ; preds = %entry
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { i32*, i32, i32 } @main.SliceInt(i32* dereferenceable_or_null(4) %ptr,
i32 %len, i8* %context) unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.SliceInt(ptr dereferenceable_or_null(4) %ptr, i32
%len, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp ugt i32 %len, 1073741823
+- %1 = icmp eq i32* %ptr, null
++ %1 = icmp eq ptr %ptr, null
+ %2 = icmp ne i32 %len, 0
+ %3 = and i1 %1, %2
+ %4 = or i1 %3, %0
+ br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
+
+ unsafe.Slice.next: ; preds = %entry
+- %5 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
+- %6 = insertvalue { i32*, i32, i32 } %5, i32 %len, 1
+- %7 = insertvalue { i32*, i32, i32 } %6, i32 %len, 2
+- %8 = bitcast i32* %ptr to i8*
+- call void @runtime.trackPointer(i8* %8, i8* undef) #2
+- ret { i32*, i32, i32 } %7
++ %5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
++ %6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1
++ %7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2
++ call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
++ ret { ptr, i32, i32 } %7
+
+ unsafe.Slice.throw: ; preds = %entry
+- call void @runtime.unsafeSlicePanic(i8* undef) #2
++ call void @runtime.unsafeSlicePanic(ptr undef) #2
+ unreachable
+ }
+
+-declare void @runtime.unsafeSlicePanic(i8*) #0
++declare void @runtime.unsafeSlicePanic(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden { i8*, i32, i32 } @main.SliceUint16(i8* dereferenceable_or_null(1) %ptr,
i16 %len, i8* %context) unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.SliceUint16(ptr dereferenceable_or_null(1) %ptr,
i16 %len, ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = icmp eq i8* %ptr, null
++ %0 = icmp eq ptr %ptr, null
+ %1 = icmp ne i16 %len, 0
+ %2 = and i1 %0, %1
+ br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next
+
+ unsafe.Slice.next: ; preds = %entry
+ %3 = zext i16 %len to i32
+- %4 = insertvalue { i8*, i32, i32 } undef, i8* %ptr, 0
+- %5 = insertvalue { i8*, i32, i32 } %4, i32 %3, 1
+- %6 = insertvalue { i8*, i32, i32 } %5, i32 %3, 2
+- call void @runtime.trackPointer(i8* %ptr, i8* undef) #2
+- ret { i8*, i32, i32 } %6
++ %4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
++ %5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1
++ %6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2
++ call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
++ ret { ptr, i32, i32 } %6
+
+ unsafe.Slice.throw: ; preds = %entry
+- call void @runtime.unsafeSlicePanic(i8* undef) #2
++ call void @runtime.unsafeSlicePanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { i32*, i32, i32 } @main.SliceUint64(i32* dereferenceable_or_null(4) %ptr,
i64 %len, i8* %context) unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.SliceUint64(ptr dereferenceable_or_null(4) %ptr,
i64 %len, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp ugt i64 %len, 1073741823
+- %1 = icmp eq i32* %ptr, null
++ %1 = icmp eq ptr %ptr, null
+ %2 = icmp ne i64 %len, 0
+ %3 = and i1 %1, %2
+ %4 = or i1 %3, %0
+@@ -290,23 +274,22 @@ entry:
+
+ unsafe.Slice.next: ; preds = %entry
+ %5 = trunc i64 %len to i32
+- %6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
+- %7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
+- %8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
+- %9 = bitcast i32* %ptr to i8*
+- call void @runtime.trackPointer(i8* %9, i8* undef) #2
+- ret { i32*, i32, i32 } %8
++ %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
++ %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
++ %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
++ call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
++ ret { ptr, i32, i32 } %8
+
+ unsafe.Slice.throw: ; preds = %entry
+- call void @runtime.unsafeSlicePanic(i8* undef) #2
++ call void @runtime.unsafeSlicePanic(ptr undef) #2
+ unreachable
+ }
+
+ ; Function Attrs: nounwind
+-define hidden { i32*, i32, i32 } @main.SliceInt64(i32* dereferenceable_or_null(4) %ptr,
i64 %len, i8* %context) unnamed_addr #1 {
++define hidden { ptr, i32, i32 } @main.SliceInt64(ptr dereferenceable_or_null(4) %ptr,
i64 %len, ptr %context) unnamed_addr #1 {
+ entry:
+ %0 = icmp ugt i64 %len, 1073741823
+- %1 = icmp eq i32* %ptr, null
++ %1 = icmp eq ptr %ptr, null
+ %2 = icmp ne i64 %len, 0
+ %3 = and i1 %1, %2
+ %4 = or i1 %3, %0
+@@ -314,15 +297,14 @@ entry:
+
+ unsafe.Slice.next: ; preds = %entry
+ %5 = trunc i64 %len to i32
+- %6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
+- %7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
+- %8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
+- %9 = bitcast i32* %ptr to i8*
+- call void @runtime.trackPointer(i8* %9, i8* undef) #2
+- ret { i32*, i32, i32 } %8
++ %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
++ %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
++ %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
++ call void @runtime.trackPointer(ptr %ptr, ptr undef) #2
++ ret { ptr, i32, i32 } %8
+
+ unsafe.Slice.throw: ; preds = %entry
+- call void @runtime.unsafeSlicePanic(i8* undef) #2
++ call void @runtime.unsafeSlicePanic(ptr undef) #2
+ unreachable
+ }
+
+diff --git a/compiler/testdata/string.ll b/compiler/testdata/string.ll
+index 5e1f924c..bd3b8f5a 100644
+--- a/compiler/testdata/string.ll
++++ b/compiler/testdata/string.ll
+@@ -3,96 +3,96 @@ source_filename = "string.go"
+ target datalayout =
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+ target triple = "wasm32-unknown-wasi"
+
+-%runtime._string = type { i8*, i32 }
++%runtime._string = type { ptr, i32 }
+
+ @"main$string" = internal unnamed_addr constant [3 x i8] c"foo",
align 1
+
+-declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
++declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
+
+-declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
++declare void @runtime.trackPointer(ptr nocapture readonly, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden void @main.init(i8* %context) unnamed_addr #1 {
++define hidden void @main.init(ptr %context) unnamed_addr #1 {
+ entry:
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._string @main.someString(i8* %context) unnamed_addr #1 {
++define hidden %runtime._string @main.someString(ptr %context) unnamed_addr #1 {
+ entry:
+- ret %runtime._string { i8* getelementptr inbounds ([3 x i8], [3 x i8]*
@"main$string", i32 0, i32 0), i32 3 }
++ ret %runtime._string { ptr @"main$string", i32 3 }
+ }
+
+ ; Function Attrs: nounwind
+-define hidden %runtime._string @main.zeroLengthString(i8* %context) unnamed_addr #1 {
++define hidden %runtime._string @main.zeroLengthString(ptr %context) unnamed_addr #1 {
+ entry:
+ ret %runtime._string zeroinitializer
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i32 @main.stringLen(i8* %s.data, i32 %s.len, i8* %context) unnamed_addr #1
{
++define hidden i32 @main.stringLen(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #1
{
+ entry:
+ ret i32 %s.len
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i8 @main.stringIndex(i8* %s.data, i32 %s.len, i32 %index, i8* %context)
unnamed_addr #1 {
++define hidden i8 @main.stringIndex(ptr %s.data, i32 %s.len, i32 %index, ptr %context)
unnamed_addr #1 {
+ entry:
+ %.not = icmp ult i32 %index, %s.len
+ br i1 %.not, label %lookup.next, label %lookup.throw
+
+ lookup.next: ; preds = %entry
+- %0 = getelementptr inbounds i8, i8* %s.data, i32 %index
+- %1 = load i8, i8* %0, align 1
++ %0 = getelementptr inbounds i8, ptr %s.data, i32 %index
++ %1 = load i8, ptr %0, align 1
+ ret i8 %1
+
+ lookup.throw: ; preds = %entry
+- call void @runtime.lookupPanic(i8* undef) #2
++ call void @runtime.lookupPanic(ptr undef) #2
+ unreachable
+ }
+
+-declare void @runtime.lookupPanic(i8*) #0
++declare void @runtime.lookupPanic(ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.stringCompareEqual(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32
%s2.len, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.stringCompareEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32
%s2.len, ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = call i1 @runtime.stringEqual(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32
%s2.len, i8* undef) #2
++ %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32
%s2.len, ptr undef) #2
+ ret i1 %0
+ }
+
+-declare i1 @runtime.stringEqual(i8*, i32, i8*, i32, i8*) #0
++declare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.stringCompareUnequal(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32
%s2.len, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.stringCompareUnequal(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32
%s2.len, ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = call i1 @runtime.stringEqual(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32
%s2.len, i8* undef) #2
++ %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32
%s2.len, ptr undef) #2
+ %1 = xor i1 %0, true
+ ret i1 %1
+ }
+
+ ; Function Attrs: nounwind
+-define hidden i1 @main.stringCompareLarger(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32
%s2.len, i8* %context) unnamed_addr #1 {
++define hidden i1 @main.stringCompareLarger(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32
%s2.len, ptr %context) unnamed_addr #1 {
+ entry:
+- %0 = call i1 @runtime.stringLess(i8* %s2.data, i32 %s2.len, i8* %s1.data, i32 %s1.len,
i8* undef) #2
++ %0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len,
ptr undef) #2
+ ret i1 %0
+ }
+
+-declare i1 @runtime.stringLess(i8*, i32, i8*, i32, i8*) #0
++declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #0
+
+ ; Function Attrs: nounwind
+-define hidden i8 @main.stringLookup(i8* %s.data, i32 %s.len, i8 %x, i8* %context)
unnamed_addr #1 {
++define hidden i8 @main.stringLookup(ptr %s.data, i32 %s.len, i8 %x, ptr %context)
unnamed_addr #1 {
+ entry:
+ %0 = zext i8 %x to i32
+ %.not = icmp ult i32 %0, %s.len
+ br i1 %.not, label %lookup.next, label %lookup.throw
+
+ lookup.next: ; preds = %entry
+- %1 = getelementptr inbounds i8, i8* %s.data, i32 %0
+- %2 = load i8, i8* %1, align 1
++ %1 = getelementptr inbounds i8, ptr %s.data, i32 %0
++ %2 = load i8, ptr %1, align 1
+ ret i8 %2
+
+ lookup.throw: ; preds = %entry
+- call void @runtime.lookupPanic(i8* undef) #2
++ call void @runtime.lookupPanic(ptr undef) #2
+ unreachable
+ }
+
+diff --git a/go.mod b/go.mod
+index a50f1174..b985effc 100644
+--- a/go.mod
++++ b/go.mod
+@@ -17,7 +17,7 @@ require (
+
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
+
golang.org/x/tools v0.1.11
+ gopkg.in/yaml.v2 v2.4.0
+-
tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec
++
tinygo.org/x/go-llvm v0.0.0-20220922115213-dcb078a26266
+ )
+
+ require (
+diff --git a/go.sum b/go.sum
+index 4af03408..d3180085 100644
+--- a/go.sum
++++ b/go.sum
+@@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod
h1:Co6ibVJAznAaIkqp8
+ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+-tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec
h1:FYtAFrw/YQPc644uNN65dW50FrEuVNaPBf70x23ApY4=
+-tinygo.org/x/go-llvm v0.0.0-20220922113433-4b5ad7ff76ec/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
++tinygo.org/x/go-llvm v0.0.0-20220922115213-dcb078a26266
h1:vg4sYKEM+w6epr5S1nXqP/7UhMYcc8nRt7Ohkq28rok=
++tinygo.org/x/go-llvm v0.0.0-20220922115213-dcb078a26266/go.mod
h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+diff --git a/interp/interpreter.go b/interp/interpreter.go
+index 83fd2cd9..c61ce7cf 100644
+--- a/interp/interpreter.go
++++ b/interp/interpreter.go
+@@ -356,7 +356,7 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ default:
+ panic("unknown integer type width")
+ }
+- case strings.HasPrefix(callFn.name, "llvm.memcpy.p0i8.p0i8.") ||
strings.HasPrefix(callFn.name, "llvm.memmove.p0i8.p0i8."):
++ case strings.HasPrefix(callFn.name, "llvm.memcpy.p0") ||
strings.HasPrefix(callFn.name, "llvm.memmove.p0"):
+ // Copy a block of memory from one pointer to another.
+ dst, err := operands[1].asPointer(r)
+ if err != nil {
+@@ -496,7 +496,7 @@ func (r *runner) run(fn *function, params []value, parentMem
*memoryView, indent
+ typecodeID := typecodeIDBitCast.Operand(0).Initializer()
+
+ // Load the method set, which is part of the typecodeID object.
+- methodSet := r.builder.CreateExtractValue(typecodeID, 2,
"").Operand(0).Initializer()
++ methodSet := stripPointerCasts(r.builder.CreateExtractValue(typecodeID, 2,
"")).Initializer()
+
+ // We don't need to load the interface method set.
+
+@@ -1095,3 +1095,15 @@ func intPredicateString(predicate llvm.IntPredicate) string {
+ return "cmp?"
+ }
+ }
++
++// Strip some pointer casts. This is probably unnecessary once support for
++// LLVM 14 (non-opaque pointers) is dropped.
++func stripPointerCasts(value llvm.Value) llvm.Value {
++ if !value.IsAConstantExpr().IsNil() {
++ switch value.Opcode() {
++ case llvm.GetElementPtr, llvm.BitCast:
++ return stripPointerCasts(value.Operand(0))
++ }
++ }
++ return value
++}
+diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go
+index cde8e2d9..4e24b923 100644
+--- a/src/runtime/runtime.go
++++ b/src/runtime/runtime.go
+@@ -27,18 +27,18 @@ func GOROOT() string {
+
+ // Copy size bytes from src to dst. The memory areas must not overlap.
+ // This function is implemented by the compiler as a call to a LLVM intrinsic
+-// like llvm.memcpy.p0i8.p0i8.i32(dst, src, size, false).
++// like llvm.memcpy.p0.p0.i32(dst, src, size, false).
+ func memcpy(dst, src unsafe.Pointer, size uintptr)
+
+ // Copy size bytes from src to dst. The memory areas may overlap and will do the
+ // correct thing.
+ // This function is implemented by the compiler as a call to a LLVM intrinsic
+-// like llvm.memmove.p0i8.p0i8.i32(dst, src, size, false).
++// like llvm.memmove.p0.p0.i32(dst, src, size, false).
+ func memmove(dst, src unsafe.Pointer, size uintptr)
+
+ // Set the given number of bytes to zero.
+ // This function is implemented by the compiler as a call to a LLVM intrinsic
+-// like llvm.memset.p0i8.i32(ptr, 0, size, false).
++// like llvm.memset.p0.i32(ptr, 0, size, false).
+ func memzero(ptr unsafe.Pointer, size uintptr)
+
+ // This intrinsic returns the current stack pointer.
+diff --git a/targets/esp32c3.json b/targets/esp32c3.json
+index d7e3fc71..d377fcec 100644
+--- a/targets/esp32c3.json
++++ b/targets/esp32c3.json
+@@ -1,6 +1,6 @@
+ {
+ "inherits": ["riscv32"],
+- "features": "+c,+m",
++ "features": "+c,+m,-relax,-save-restore",
+ "build-tags": ["esp32c3", "esp"],
+ "serial": "uart",
+ "rtlib": "compiler-rt",
+diff --git a/targets/fe310.json b/targets/fe310.json
+index e33308f2..2c9e6b5c 100644
+--- a/targets/fe310.json
++++ b/targets/fe310.json
+@@ -1,6 +1,6 @@
+ {
+ "inherits": ["riscv32"],
+ "cpu": "sifive-e31",
+- "features": "+a,+c,+m",
++ "features": "+a,+c,+m,-64bit,-relax,-save-restore",
+ "build-tags": ["fe310", "sifive"]
+ }
+diff --git a/targets/k210.json b/targets/k210.json
+index 41c39f44..cc0d2ed4 100644
+--- a/targets/k210.json
++++ b/targets/k210.json
+@@ -1,6 +1,6 @@
+ {
+ "inherits": ["riscv64"],
+- "features": "+64bit,+a,+c,+d,+f,+m",
++ "features": "+64bit,+a,+c,+d,+f,+m,-relax,-save-restore",
+ "build-tags": ["k210", "kendryte"],
+ "code-model": "medium"
+ }
+diff --git a/targets/riscv-qemu.json b/targets/riscv-qemu.json
+index 84050ff6..d55a685c 100644
+--- a/targets/riscv-qemu.json
++++ b/targets/riscv-qemu.json
+@@ -1,6 +1,6 @@
+ {
+ "inherits": ["riscv32"],
+- "features": "+a,+c,+m",
++ "features": "+a,+c,+m,-relax,-save-restore",
+ "build-tags": ["virt", "qemu"],
+ "default-stack-size": 4096,
+ "linkerscript": "targets/riscv-qemu.ld",
+diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go
+index 9e2ffa90..55d1af39 100644
+--- a/transform/interface-lowering.go
++++ b/transform/interface-lowering.go
+@@ -305,7 +305,9 @@ func (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet
llvm.Value)
+ // no methods or methods already read
+ return
+ }
+- methodSet = methodSet.Operand(0) // get global from GEP
++ if !methodSet.IsAConstantExpr().IsNil() && methodSet.Opcode() ==
llvm.GetElementPtr {
++ methodSet = methodSet.Operand(0) // get global from GEP, for LLVM 14 (non-opaque
pointers)
++ }
+
+ // This type has methods, collect all methods of this type.
+ t.methodSet = methodSet
+diff --git a/transform/interrupt.go b/transform/interrupt.go
+index b15ff8a9..043eebb8 100644
+--- a/transform/interrupt.go
++++ b/transform/interrupt.go
+@@ -36,9 +36,8 @@ func LowerInterrupts(mod llvm.Module) []error {
+ handleMap := map[int64][]llvm.Value{}
+ handleType := mod.GetTypeByName("runtime/interrupt.handle")
+ if !handleType.IsNil() {
+- handlePtrType := llvm.PointerType(handleType, 0)
+ for global := mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
+- if global.Type() != handlePtrType {
++ if global.GlobalValueType() != handleType {
+ continue
+ }
+
+diff --git a/transform/llvm.go b/transform/llvm.go
+index 7042b32d..045bb050 100644
+--- a/transform/llvm.go
++++ b/transform/llvm.go
+@@ -80,6 +80,12 @@ func replaceGlobalIntWithArray(mod llvm.Module, name string, buf
interface{}) ll
+ // stripPointerCasts strips instruction pointer casts (getelementptr and
+ // bitcast) and returns the original value without the casts.
+ func stripPointerCasts(value llvm.Value) llvm.Value {
++ if !value.IsAConstantExpr().IsNil() {
++ switch value.Opcode() {
++ case llvm.GetElementPtr, llvm.BitCast:
++ return stripPointerCasts(value.Operand(0))
++ }
++ }
+ if !value.IsAInstruction().IsNil() {
+ switch value.InstructionOpcode() {
+ case llvm.GetElementPtr, llvm.BitCast:
+diff --git a/transform/reflect.go b/transform/reflect.go
+index 68beba9b..b994df61 100644
+--- a/transform/reflect.go
++++ b/transform/reflect.go
+@@ -251,7 +251,10 @@ func LowerReflect(mod llvm.Module) {
+ // a pointer to a runtime.structField array and therefore a
+ // bitcast. This global should be erased separately, otherwise
+ // typecode objects cannot be erased.
+- structFields := references.Operand(0)
++ structFields := references
++ if !structFields.IsAConstantExpr().IsNil() && structFields.Opcode() ==
llvm.BitCast {
++ structFields = structFields.Operand(0) // get global from bitcast, for LLVM 14
compatibility (non-opaque pointers)
++ }
+ structFields.EraseFromParentAsGlobal()
+ }
+ }
+@@ -460,7 +463,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode
llvm.Value) int
+
+ // Get the fields this struct type contains.
+ // The struct number will be the start index of
+- structTypeGlobal := state.builder.CreateExtractValue(typecode.Initializer(), 0,
"").Operand(0).Initializer()
++ structTypeGlobal :=
stripPointerCasts(state.builder.CreateExtractValue(typecode.Initializer(), 0,
"")).Initializer()
+ numFields := structTypeGlobal.Type().ArrayLength()
+
+ // The first data that is stored in the struct sidetable is the number of
+@@ -483,7 +486,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode
llvm.Value) int
+ if nameGlobal == llvm.ConstPointerNull(nameGlobal.Type()) {
+ panic("compiler: no name for this struct field")
+ }
+- fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0), state.builder)
++ fieldNameBytes := getGlobalBytes(stripPointerCasts(nameGlobal), state.builder)
+ fieldNameNumber := state.getStructNameNumber(fieldNameBytes)
+
+ // See whether this struct field has an associated tag, and if so,
+@@ -493,7 +496,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode
llvm.Value) int
+ tagNumber := 0
+ if tagGlobal != llvm.ConstPointerNull(tagGlobal.Type()) {
+ hasTag = true
+- tagBytes := getGlobalBytes(tagGlobal.Operand(0), state.builder)
++ tagBytes := getGlobalBytes(stripPointerCasts(tagGlobal), state.builder)
+ tagNumber = state.getStructNameNumber(tagBytes)
+ }
+
+diff --git a/transform/rtcalls.go b/transform/rtcalls.go
+index d70bc626..209e15ae 100644
+--- a/transform/rtcalls.go
++++ b/transform/rtcalls.go
+@@ -139,14 +139,13 @@ func OptimizeReflectImplements(mod llvm.Module) {
+ if call.IsACallInst().IsNil() {
+ continue
+ }
+- interfaceTypeBitCast := call.Operand(2)
+- if interfaceTypeBitCast.IsAConstantExpr().IsNil() || interfaceTypeBitCast.Opcode() !=
llvm.BitCast {
++ interfaceType := stripPointerCasts(call.Operand(2))
++ if interfaceType.IsAGlobalVariable().IsNil() {
+ // The asserted interface is not constant, so can't optimize this
+ // code.
+ continue
+ }
+
+- interfaceType := interfaceTypeBitCast.Operand(0)
+ if strings.HasPrefix(interfaceType.Name(), "reflect/types.type:named:") {
+ // Get the underlying type.
+ interfaceType = builder.CreateExtractValue(interfaceType.Initializer(), 0,
"")
+--
+2.36.1
+
diff --git a/compiler-rt-release-keys.asc b/compiler-rt-release-keys.asc
new file mode 100644
index 0000000..0d3789a
--- /dev/null
+++ b/compiler-rt-release-keys.asc
@@ -0,0 +1,104 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQGNBGLtemUBDADClvDIromq0Y4TX+wyRyYCq5WusPQheQuY8dVCXd9KhMpYAv8U
+X15E5boH/quGpJ0ZlVkWcf+1WUHIrQWlbzQdIx514CDM7DBgO92CXsnn86kIMDW+
+9S+Hkn8upbizT1fWritlHwzD9osz7ZQRq7ac03PPgw27tqeIizHGuG4VNLyhbbjA
+w+0VLFSu3r219eevS+lzBIvR5U9W720jFxWxts4UvaGuD6XW1ErcsTvuhgyCKrrs
+gxO5Ma/V7r0+lqRL688ZPr4HxthwsON1YCfpNiMZ6sgxT8rOE0qL/d07ItbnXxz6
+KdcNWIXamTJKJgag6Tl0gYX4KIuUCcivXaRdJtUcFFsveCorkdHkdGNos403XR89
+5u9gq7Ef10Zahsv5GjE2DV5oFCEhXvfIWxvyeJa65iBkJafElb2stgUjkIut2a2u
++XmpKpwpGSFklce1ABLrmazlLjhsYiJVrz5l5ktoT9moE4GaF7Q5LD6JgsxzLE0U
+Tzo9/AQPd8qG2REAEQEAAbQeVG9iaWFzIEhpZXRhIDx0b2JpYXNAaGlldGEuc2U+
+iQHUBBMBCAA+FiEE1XS9XR0OmIleO/kARPJIXkXVkEIFAmLtemUCGwMFCRLMAwAF
+CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQRPJIXkXVkEKoNwv+MEMVzdnzJarx
+ZJ0OzHrGJJG8/chkuoejTjCLG73li9yWQigy5KmvynB5yW0fk0PAQ90vvp2wr/Hd
+mUh0Zda3CwF6sWlO3N6DEDjVA3lZUuofTtvMn/tdGvvOOXYXAP9N+SZfp/7q8dxX
+zn5SA1AO87nXq5lrwVzlVzUCdwOeqDlJ+2U9VEqvukP/FdkgaR2bEb8Wm/h+encW
+UIQEqPDE+qOyJ9dRaiL0CUI4x+1wXeXB3OA7VybF2LvaZDbMlocdy+vs825iUWfa
+n8g3mE2TpV8jkc9UHgGGopzxqNquvkkIB7ZFZm/PSW40W3OeHKhYsZZbHrz9403t
+3R4SAzA3ApmMP/P8ue9irsbe24g3rzYMvck1w4C1a4Uy9buT0OCfA+dA16IRAPgV
+5SJEIS62cFbUxkw8el3rUK9V+6kwoq4k8Fs8f1U7DEnOKS/v8BJJCNEc1cvimZai
+Y5/3r5BeneEmuZFKX4iIIfcn5PmLSDB4aw+gKAIAAus+E2DxBqE+uQGNBGLtemUB
+DADBCNyvUdv0OV//6pQ/0YC2bYXL/ElF0rOjFFl4H7O3TRxgIz2C4nQJHUOrXSmo
+iL7ldfUjoAMgebcoWDpgE8S2Vjw2Gd+UJBQXj+3J6dPKLBUCjj9CLyb5hwOHITMV
+b9UC/E+iwpn4vgTbI6K1O847brkBC+GuDT4g9D3O3sRbja0GjN0n2yZiS8NtRQm1
+MXAVy1IffeXKpGLookAhoUArSN88koMe+4Nx6Qun4/aUcwz0P2QUr5MA5jUzFLy1
+R3M5p1nctX15oLOU33nwCWuyjvqkxAeAfJMlkKDKYX25u1R2RmQ4ju2kAbw0PiiZ
+yYft8fGlrwT4/PB3AqfKeSpx8l9Vs15ePvcuJITauo3fhBjJ6Y4WCKlTG1FbDYUl
+KvPhyGO8yLhtZJg3+LbA5M/CEHsDmUh7YEQVxM0RTQMTxNBVBF5IG/4y8v/+19DZ
+89VdpsQF3ThoPV0yh57YMemTBeIxpF9Swp5N7kUWct4872kBnXOmbp/jhU4MpLj6
+iLEAEQEAAYkBvAQYAQgAJhYhBNV0vV0dDpiJXjv5AETySF5F1ZBCBQJi7XplAhsM
+BQkSzAMAAAoJEETySF5F1ZBCdPwL/3Ox6MwrKFzYJNz3NpQFpKFdDrkwhf25D/Qw
+vu5e8Lql/q62NIhEKH3jxXXgoFYas2G7r8CSCRehraDqvXygbaiWUIkxSU0xuDTl
+lNqHSkCRqIxhi/yxNm1Pk84NVGTLXWW0+CwT9cRwWn5foIPJhoDdZ732zJ7rcY3R
+g71SJTe3R6MnGBzIF1LzT7Znwkh7YfcmeTfInareIWXpeNaeKy8KrQmr/0+5AIer
+Ax1gu03o8GD5LFDUuGbESgDJU6nVtVyht7C6AlJWqSX6QS3+lPCw5BOCKbxakYNR
+/oBNauzyDISdbUwzHM2d+XGCjBsXKRA0Tft2NlG6EC83/PuY2J9MSA2gg3iPHsiN
+J5iipbdZNpZ3XL0l8/t/7T60nM7UZDqt3twLMA0eRFRlCnhMjvFE5Zgj5DE7BsJh
+w2nCoGWkAcfeuih+jfyEjN24NK+sE/bM+krwVv430ewJwm1bVUqKrbOb9aa6V9gP
+9RmlwZlOTFGcWBYl/cfRONn9qi9a6w==
+=Lvw+
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFrqgT0BEAC7xo0WH+eNrLlU5LrCk59KmImn1abFcmWNd8kYr5XfqmJKyVqo
+EY7A/yRjf+Yn1621EDkpKPjbql7q7MlZMpqKVdOWKWgmhvz08IOKJxaIABd/iIRT
+FwhIvB68YjtmzcoOJRi1wLnwuG55fJ9E69HyZ33jgAlRaWV3bE/YyszoTlZriUOE
+RbzC5WzX004cE9evlrr+YLt5Y6z7tntOdSXPLyGOFAO5LYMsHsEdi2JBYWrjlslG
+6iJr5iEt9v442PrJ79YYbu5QWe/6APRWtI3AtKBp7y250oon2lbj+bIVD7U9fOBB
+n/Frqx54UN22sJycET63hgYW4pIjIi5zq+FF15aU+ZqBdtNltoX4hEN7wlDpuNc0
+ezVu2Z8hdt8thpjiFUioTQ1t3RmsN6N548VwxmHdoYpAmiZqPIYBYvm85JB7S/3h
+RLuoeGxufBhXGCpnG8ghTOGtbbdanuLB/UROFXTdyZbTCBN5S6jvwkPSaHG7H35Z
+3fazMriTXwL1RGAbKITSWhDe5dXy/yOInWe8emJx+35vwQYCB2L4S8wRyQyRw6x4
+YoXCscW041DUMBX2CC7SjMCcmAC39UX1c3GbTpS3rkJR9cmXt50nviMnKpIwlIPd
+ZYhmxKifwTJ70+c4GVK2o0MG9bTYvpYhLnYxv6iJCfgmT40E+qkDSzSoZwARAQAB
+tCJUb20gU3RlbGxhcmQgPHRzdGVsbGFyQHJlZGhhdC5jb20+iQI/BBMBAgApBQJa
+6oE9AhsDBQkB4TOABwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQoseUqYZB
+nYp8Gg//RmX6Nup/Dv05jTL7dKRBSD08MF400tRtTmRhIuAgGv27qO2hbqzprKVu
+vd20vKBB9CNZpXC2oY8k9VhGv2PZNi/X7iuULIYmzjeFMbJ5CjU6XvuUBmNasITH
+6K/0KLhGebPs5h/DNtd7lbzDm86dLcjxgl6LXUULaSyYvTAKn6YB6mAv5J3qJs2X
+lfTmenNh9p7TPFTfcMHcS70ywjqKXlDiH0q9bRKJnSX7xUFlTHjKkNnAcRjlPaGf
+wUUhIPrnpDboqfwfcmScLrHANW9nwFWSFkNAJu1HQUEuF+An/RZUHDxFbLPKKAIp
+hwZ0aORTfBVZ80AjehDMYCbmp1DJeTyLjC1/94un6mlxPIKnPPPM8rMxr83xnrvP
++Y1+pJaDUL7ZvKnmt2LrGRa9GvsNiYKpCNCORfiwZTeSxxXb+LgaodnbCHvGBnk7
+nlbLdMY08vNlxSx8LNyG0krFxJw/rq260+73yc+qjENeG68fozTEy/4jSVrF4t3m
+8AAUu5r6i/Aomo7Q27TjU928bbCVunpvDpserfDqr3zsA96LO9k8T6THR6zC9i+R
+LiN9Vjl+Rr2YuU26DjFYkCNEA2kNflYCWPJi5I0eodTPZrIPBWJ+H0YTRX31bMH9
+X88FnWJuCwaqAMN3rWlX/lXNCouWDdCuPWseZApISAMnVDE2mM+JAlYEEwEIAEAC
+GwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgBYhBEdOIjFqv0eFqIxujqLHlKmG
+QZ2KBQJgkytfBQkJaxEiAAoJEKLHlKmGQZ2Kv8YP/jNPjcMAP0ZTpUcYV46mGKwf
+aQ0g5FUMSfxP7uJHtctj2dUckPGpA9SAH+ApiJutVgTQpWqNJKPd2vVxOiu5sywN
+iDKCOMlKug5m6lgLX5h3zBvSN90Hpn4I0qHRA3rgENLoPs/UYBxohvFPIhOOjPqO
+HIUuSPhAIuIZawxtqlADswHiKPy38Ao5GnWRb60zKfrB+N+ZiOtg7ITrlTGYm2tX
+0W9iWUG32gIA/RX2qmFPoLrDFqsk66Eir0Ghk5gppRrmpEl/M1lqA8bxlqWto/8w
+V8yDbSEu5fmM3WN3OUcSA23lYJi4j656Q4hS5PU+IWuZbBhcpYwDGexV5+m/ySZb
+wtHZMIb4Au+dgJHCvRiSqHgplyfiamxX5CfA0DJVHoGXpBOw8a2geRT0+DrjSbOS
++CDDnlfmQLfHgjEuyQPU8V0Wlb0tJEvnPPqNPmAv0Rv7MC4qmD/zDrgwuddpfr1x
+H+nWus2plR8E6p/x9uvPLb3plJ94ri1XjXiJPyPvqzBAwA40Zeg0rE7sTVwCC3E9
+RZa7dHh17exkcZdOIS/vRQ1G/VNaOVUwrcC/vIMgZSe37bCLeOKViMtacAiBJDjo
+INC1QJ2F3CYVwktrcgmuz9S8e2WrqdTWwijjConB80EwfHQllz5sp/jU6Bgv297X
+UXkgpk1y+ibQ9/syRQpFuQINBFrqgT0BEADB2vDHMuexkaUm3rPi6SvyMGcsHWle
+feAWm+UjROKIaV77rHwo0/8ncKbtoQx4ZZjDXdI77M2bXB7tPgyEML90bWDMMGN/
+gnpwWSsiDRWpFIV/+hD6B+l9UaEi4UvEstUbIchOkGrZgPZ4Qism4FSVosEK+FE7
+EKCT4PSS+LiBKSxJZB8/g2uX+3pJvVxYurvcVpTmiNlXvUyll4KMpzy5e0KKa/0y
+w9h7SAre5399cSM8E7PDQZQDb1EwbyVyO2yDLgs+p3yzPtRJAydaqRPmT1JbSCYf
+hcihTrViMA4EDN5GRjH2EElI37+2HMpgLs4rc6Abz1F4FUVFhqWJXCKUcAIrG17w
+A7YUlYg38S6Xws2Xj1VfZ/WP7/qIMJZidYTHZbN9WWCaifCPfLlE5VDNsa8y6Mxm
+uFMBAB4PpB1gmmP9pPZsOzV9SmeYt8h2P8cVKDW2f56azpBZvZX6NFn8e0+ZDXS4
+8BQz31G2Xdfa3uOEV0J3JxPXcEbfuPzDHb7OMYP+2Ypjox1TozT1e9zr46SQl9OF
+MglOBnwLZJ9baA/IqZkqLq5iu5Oqda44EIVNAntQ3gebi3+q3YG1SvNUseIy2+8y
+cNWtdDuWv366Af0okCdrKAdap8+KbREer9uXhamtvxc49RCoWwuKoKfBz0RdVvMv
+R/Py2xV8A7PaIQARAQABiQIlBBgBAgAPBQJa6oE9AhsMBQkB4TOAAAoJEKLHlKmG
+QZ2KAaMQALHif2E0PBLVt09vlr4i8jAsQvDrzRajmVPd2B9RpfNU6HJe/y93SZd2
+udr9vzgmfd2o5u12vbegKNiMRgp1VyHQDmYlce27jrH5aPuKmos78+o5/p5yPWCv
+Rj8zxGKh7le7UPO+7UveKu+bgb3zwTj6bEuHX7fVI+WjGmEH3bbjDGamWxXrpfGc
+7+Jr8TN4ZO2OwYBcFOS9U2ZQ6TxrPaCSIm6+j8f+a9HPOuuDc62mMuV/EWQZy0i7
+DhDqU2PNpVjQDWQNpHA8oLDrjNFAoJS8gbHABVsFM1VnwBNT2MKcZQmm05dlQ+ll
+S6meHNCvTniKIKC+Giz1Yd5JVGDACZWWPxEz6VhpQW/twkxRqwlUdpFt7UgDquTL
+M1beQUCZRt81yJTNdrggbhQ2POxOdIO0CPiQv7U1IzndZp6baedeBw4a7FCbj6GY
+cQeHxQCrWpQrwigiseG5uhhS9aiaVFEHja9baSLfXlZu/vsR4MdDG5/iEpier/Xw
+h1qnpTSY+r31Uw3lTUlPHzlg47PMgPslaIhCzfVggxh9bTqxcDbuYJ7NuoMho3tN
+yWfeofTJ7PhKzoXM2Y/rRFoM5gNh1RVA19ngLT5Jwiof8fPZvHJ/9ZkHn+O7eMNm
+m5++gYza3pnn2/PoGpGGAKok+sfJiq5Tb7RUefyJTeZiyTZ/XJrA
+=tMzl
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/sources b/sources
index 4597e0f..7f554f3 100644
--- a/sources
+++ b/sources
@@ -2,8 +2,8 @@ SHA512 (tinygo-0.26.0.tar.gz) =
7b95f6b4356545b806207092fa315863446227e3f90d05ab
SHA512 (avr-6624554c02b237b23dc17d53e992bf54033fc228.tar.gz) =
1aa157bd761db38f8680614fa1cf47d7009508f65291b7eaaa5aba1ae76d35103f68a42947b7269a170d2f1cf8fb09941a5d74070fe6d204b68dd15a9ad2ed29
SHA512 (cmsis-9fe411cef1cef5de58e5957b89760759de44e393-clean.tar.xz) =
f131fc241f61982c49f334eb502c2f13da61eb7bdaa641ee84a8de30c4d576b735b8aadeafd7d75351473a2df6a42de6a236ecc5dcc616ee6cfcc07af29446f9
SHA512 (cmsis_svd-df75ff974c76a911fc2815e29807f5ecaae06fc2-clean.tar.xz) =
8abbc6f366aed9571a74a4b6e7065ed2d6a59e0495c3745681d9a654d61edd136319788741f7afc781211adb64ed1faeafe9d6acc6be5a16d9ee48e98c5ddeb1
-SHA512 (compiler-rt-14.0.0.src.tar.xz) =
9df73ef3b81f2b70902726e0dc5529c0cc1e976ce75fbfb1c3d7930882d82fc0896934a32d1c9511b08962cac5b409c14f54dc53833fbf0724256b22165c4439
-SHA512 (compiler-rt-14.0.0.src.tar.xz.sig) =
3998c7a7477a95ae36591b8658677a44f5d4c88a57e93df57fc3f4670c38a71fb0e385b7f9b44ef7e97d7ce77551b4ea790c6f63174e79a2ffc9dd678dcf886f
+SHA512 (compiler-rt-15.0.0.src.tar.xz) =
25763e581c90923260b7c3a03e220feb4cabb2757e418c4940db0eeb6a17f65b35db0c93d3c1e526adad2f6dc93595bec6d99b1bfb4a1bd13a14a0db5301e6cf
+SHA512 (compiler-rt-15.0.0.src.tar.xz.sig) =
94f39d2e30372ccea4db96c3dd4005a5b44c2bf5d22fa0aaf45b86673ef7d3460884689f97bc96470db2d546042fb01fe3ca41bf22b6323abe0cd785b85d76ef
SHA512 (macos-minimal-sdk-ebb736fda2bec7cea38dcda807518b835a539525.tar.gz) =
2f97d5826c79116c851e1efde74faf806de56ac8acc5509d1ab7690d0edf88f6e227b273d2c5ef7d894a8ada2e316e285ef4e58d74ca0c6f91584653154eae10
SHA512 (musl-1.2.0.tar.gz) =
58bd88189a6002356728cea1c6f6605a893fe54f7687595879add4eab283c8692c3b031eb9457ad00d1edd082cfe62fcc0eb5eb1d3bf4f1d749c0efa2a95fec1
SHA512 (musl-1.2.0.tar.gz.asc) =
1639d1f39f3c587011cc6e1ae44774d20d306f4d18fb394bfa86c40f52af53a882ebd5326553b589a1c5316494b77658dc3310c0187836dfd1fd023ccfedaaf0
diff --git a/tinygo.spec b/tinygo.spec
index df67c75..f358329 100644
--- a/tinygo.spec
+++ b/tinygo.spec
@@ -10,7 +10,11 @@ Version: 0.26.0
%global CMSIS_commit 9fe411cef1cef5de58e5957b89760759de44e393
%global avr_commit 6624554c02b237b23dc17d53e992bf54033fc228
+%if %{fedora} > 36
+%global clang_llvm_version 15
+%else
%global clang_llvm_version 14
+%endif
%global cmsis_svd_commit df75ff974c76a911fc2815e29807f5ecaae06fc2
%global compiler_rt_version %{clang_llvm_version}.0.0
%global macos_minsdk_commit ebb736fda2bec7cea38dcda807518b835a539525
@@ -56,7 +60,7 @@ Source3:
https://github.com/avr-rust/avr-mcu/archive/%{avr_commit}/avr-%{
Source4: cmsis_svd-%{cmsis_svd_commit}-clean.tar.xz
Source50:
https://github.com/llvm/llvm-project/releases/download/llvmorg-%{compiler...
Source51:
https://github.com/llvm/llvm-project/releases/download/llvmorg-%{compiler...
-Source52: tstellar-gpg-key.asc
+Source52:
https://src.fedoraproject.org/rpms/compiler-rt/raw/f8e98d51f0c3fdbaa9ce5d...
Source60:
https://musl.libc.org/releases/musl-%{musl_version}.tar.gz
Source61:
https://musl.libc.org/releases/musl-%{musl_version}.tar.gz.asc
Source62:
https://musl.libc.org/musl.pub
@@ -79,6 +83,22 @@ Patch0004:
0004-Suggest-optional-packages-to-install-if-missing.patch
Patch0005: 0005-Skip-TestDirFS-on-32-bit-systems.patch
Patch0006: 0006-Skip-broken-tests-on-i686.patch
+# Backport patches for LLVM 15 support
+#
https://github.com/tinygo-org/tinygo/pull/3230
+Patch0007: 0007-wasm-fix-GC-scanning-of-allocas.patch
+#
https://github.com/tinygo-org/tinygo/pull/3189
+Patch0008: 0008-compiler-return-a-FunctionType-not-a-PointerType-in-.patch
+Patch0009: 0009-all-add-type-parameter-to-CreateCall.patch
+Patch0010: 0010-all-add-type-parameter-to-CreateLoad.patch
+Patch0011: 0011-all-add-type-parameter-to-GEP-calls.patch
+Patch0012: 0012-all-replace-llvm.Const-calls-with-builder.Create-cal.patch
+Patch0013: 0013-interp-change-object.llvmType-to-the-initializer-typ.patch
+Patch0014: 0014-all-remove-pointer-ElementType-calls.patch
+Patch0015: 0015-transform-fix-memory-corruption-issues.patch
+Patch0016: 0016-riscv-add-target-abi-metadata-flag.patch
+Patch0017: 0017-interp-add-support-for-constant-icmp-instructions.patch
+Patch0018: 0018-ci-add-support-for-LLVM-15.patch
+
# Not supported upstream yet.
ExcludeArch: armv7hl ppc64le s390x
#
https://fedoraproject.org/wiki/Changes/EncourageI686LeafRemoval
diff --git a/tstellar-gpg-key.asc b/tstellar-gpg-key.asc
deleted file mode 100644
index eba625c..0000000
Binary files a/tstellar-gpg-key.asc and /dev/null differ
commit 6da6ac5b43f0787231fe086c3f47502df81a3275
Merge: d515a92 9b32d8b
Author: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun Oct 9 04:04:10 2022 -0400
Merge branch 'f36' into rawhide
diff --cc tinygo.spec
index 6ee3a96,e228822..df67c75
--- a/tinygo.spec
+++ b/tinygo.spec
@@@ -83,19 -79,8 +79,10 @@@ Patch0004: 0004-Suggest-optional-p
Patch0005: 0005-Skip-TestDirFS-on-32-bit-systems.patch
Patch0006: 0006-Skip-broken-tests-on-i686.patch
- #
https://github.com/tinygo-org/tinygo/issues/3008
- # Broken due to TestCVE202230630
- Patch0008: 0008-Temporarily-skip-io-fs-tests.patch
-
- #
https://github.com/tinygo-org/tinygo/pull/3060
- Patch0009: 0009-Add-ErrProcessDone-error.patch
- Patch0010: 0010-Fix-tinygo-test-with-Go-1.19.patch
- Patch0011: 0011-Fix-tinygo-test-with-Go-1.16.patch
-
# Not supported upstream yet.
ExcludeArch: armv7hl ppc64le s390x
+#
https://fedoraproject.org/wiki/Changes/EncourageI686LeafRemoval
+ExcludeArch: %{ix86}
BuildRequires: (clang-devel >= %{clang_llvm_version} with clang-devel < %{lua:
print(tonumber(rpm.expand('%{clang_llvm_version}')) + 1)})
BuildRequires:
golang(github.com/aykevl/go-wasm)
commit 9b32d8b0ddc883f147dfe150fbeba3c7832147a1
Author: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sat Oct 8 04:31:34 2022 -0400
Update to latest version (#2132066)
diff --git a/.gitignore b/.gitignore
index 305c25b..0f45ff4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,4 @@
/compiler-rt-12.0.0.src.tar.xz.sig
/compiler-rt-14.0.0.src.tar.xz.sig
/tinygo-0.25.0.tar.gz
+/tinygo-0.26.0.tar.gz
diff --git a/0001-Skip-WASI-tests.patch b/0001-Skip-WASI-tests.patch
index 5db9255..6ddce34 100644
--- a/0001-Skip-WASI-tests.patch
+++ b/0001-Skip-WASI-tests.patch
@@ -1,7 +1,7 @@
-From f62e55a3c636caf2a609a0290701ca7108ab4c46 Mon Sep 17 00:00:00 2001
+From 6b50974a6d4972b755a35d40d87e5bdf9c97d925 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Tue, 15 Dec 2020 05:06:04 -0500
-Subject: [PATCH 01/11] Skip WASI tests.
+Subject: [PATCH 1/6] Skip WASI tests.
We do not have wasmtime available.
@@ -11,10 +11,10 @@ Signed-off-by: Elliott Sales de Andrade
<quantum.analyst(a)gmail.com>
1 file changed, 5 deletions(-)
diff --git a/main_test.go b/main_test.go
-index f620c77d..3e97f481 100644
+index 9ddbe52f..79ae2cf2 100644
--- a/main_test.go
+++ b/main_test.go
-@@ -165,10 +165,6 @@ func TestBuild(t *testing.T) {
+@@ -154,10 +154,6 @@ func TestBuild(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("wasm", sema), tests, t)
})
@@ -25,7 +25,7 @@ index f620c77d..3e97f481 100644
}
}
-@@ -408,7 +404,6 @@ func TestTest(t *testing.T) {
+@@ -413,7 +409,6 @@ func TestTest(t *testing.T) {
// Node/Wasmtime
targ{"WASM", optionsFromTarget("wasm", sema)},
diff --git a/0002-Use-system-mingw64-headers-and-crt.patch
b/0002-Use-system-mingw64-headers-and-crt.patch
index e8dd0c8..187daab 100644
--- a/0002-Use-system-mingw64-headers-and-crt.patch
+++ b/0002-Use-system-mingw64-headers-and-crt.patch
@@ -1,7 +1,7 @@
-From 7c10e6e5debde713b52008e1f7476ffa036e2d48 Mon Sep 17 00:00:00 2001
+From 76c575659d42187b0c4c15d4f5978c4368800da7 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 2 Jan 2022 05:47:18 -0500
-Subject: [PATCH 02/11] Use system mingw64 headers and crt
+Subject: [PATCH 2/6] Use system mingw64 headers and crt
Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
---
@@ -10,7 +10,7 @@ Signed-off-by: Elliott Sales de Andrade
<quantum.analyst(a)gmail.com>
2 files changed, 7 insertions(+), 68 deletions(-)
diff --git a/builder/mingw-w64.go b/builder/mingw-w64.go
-index 135cae94..d233068d 100644
+index 27fefee0..d233068d 100644
--- a/builder/mingw-w64.go
+++ b/builder/mingw-w64.go
@@ -1,31 +1,11 @@
@@ -84,7 +84,7 @@ index 135cae94..d233068d 100644
- // .in files need to be preprocessed by a preprocessor (-E)
- // first.
- defpath = outpath + ".def"
-- err := runCCompiler("-E", "-x", "c",
"-Wp,-w", "-P", "-DDEF_X64", "-o", defpath,
inpath,
"-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/")
+- err := runCCompiler("-E", "-x", "c",
"-Wp,-w", "-P", "-DDEF_X64", "-DDATA",
"-o", defpath, inpath,
"-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/")
- if err != nil {
- return err
- }
@@ -99,10 +99,10 @@ index 135cae94..d233068d 100644
}
return jobs
diff --git a/compileopts/config.go b/compileopts/config.go
-index a006b673..c81a547c 100644
+index ebfc5082..cd49283d 100644
--- a/compileopts/config.go
+++ b/compileopts/config.go
-@@ -297,12 +297,9 @@ func (c *Config) CFlags() []string {
+@@ -304,12 +304,9 @@ func (c *Config) CFlags() []string {
root := goenv.Get("TINYGOROOT")
cflags = append(cflags,
"--sysroot="+root+"/lib/wasi-libc/sysroot")
case "mingw-w64":
diff --git a/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
b/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
index 789228d..b383fce 100644
--- a/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
+++ b/0003-Skip-some-cross-Linux-tests-where-qemu-is-broken.patch
@@ -1,7 +1,7 @@
-From 09c7cf0930704cc07844e6a926c5f8e667350730 Mon Sep 17 00:00:00 2001
+From 2a2e35e4565e8ea7f7ac2d34cb9da24000bb6474 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Mon, 3 Jan 2022 22:39:31 -0500
-Subject: [PATCH 03/11] Skip some cross Linux tests where qemu is broken
+Subject: [PATCH 3/6] Skip some cross Linux tests where qemu is broken
The upstream issues will hopefully be fixed soon:
@@ -14,10 +14,10 @@ Signed-off-by: Elliott Sales de Andrade
<quantum.analyst(a)gmail.com>
1 file changed, 28 insertions(+)
diff --git a/main_test.go b/main_test.go
-index 3e97f481..44d85249 100644
+index 79ae2cf2..9359ef0c 100644
--- a/main_test.go
+++ b/main_test.go
-@@ -250,6 +250,20 @@ func runPlatTests(options compileopts.Options, tests []string, t
*testing.T) {
+@@ -252,6 +252,20 @@ func runPlatTests(options compileopts.Options, tests []string, t
*testing.T) {
}
func emuCheck(t *testing.T, options compileopts.Options) {
@@ -38,7 +38,7 @@ index 3e97f481..44d85249 100644
// Check if the emulator is installed.
spec, err := compileopts.LoadTarget(&options)
if err != nil {
-@@ -336,6 +350,20 @@ func runTestWithConfig(name string, t *testing.T, options
compileopts.Options, c
+@@ -341,6 +355,20 @@ func runTestWithConfig(name string, t *testing.T, options
compileopts.Options, c
return
}
diff --git a/0004-Suggest-optional-packages-to-install-if-missing.patch
b/0004-Suggest-optional-packages-to-install-if-missing.patch
index 14ff89c..6f333e2 100644
--- a/0004-Suggest-optional-packages-to-install-if-missing.patch
+++ b/0004-Suggest-optional-packages-to-install-if-missing.patch
@@ -1,7 +1,7 @@
-From c995ba5cf2fb21c419dc82afe9968a020aadf182 Mon Sep 17 00:00:00 2001
+From 3f935d679870de924aa65d78c23ecdcb483ab4a3 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 6 Feb 2022 03:49:16 -0500
-Subject: [PATCH 04/11] Suggest optional packages to install if missing
+Subject: [PATCH 4/6] Suggest optional packages to install if missing
Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
---
diff --git a/0005-Skip-TestDirFS-on-32-bit-systems.patch
b/0005-Skip-TestDirFS-on-32-bit-systems.patch
index 877ec55..cdfca0d 100644
--- a/0005-Skip-TestDirFS-on-32-bit-systems.patch
+++ b/0005-Skip-TestDirFS-on-32-bit-systems.patch
@@ -1,7 +1,7 @@
-From 85a4d526d5109bbd4ca2f56fa00fd1d9fccfe065 Mon Sep 17 00:00:00 2001
+From 41cbdf1cfe50f24b49beb615f0924ea3255c7e7d Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 8 May 2022 04:18:05 -0400
-Subject: [PATCH 05/11] Skip TestDirFS on 32-bit systems
+Subject: [PATCH 5/6] Skip TestDirFS on 32-bit systems
Because Seek is not fully implemented there.
@@ -11,7 +11,7 @@ Signed-off-by: Elliott Sales de Andrade
<quantum.analyst(a)gmail.com>
1 file changed, 4 insertions(+)
diff --git a/src/os/os_anyos_test.go b/src/os/os_anyos_test.go
-index d8ac01c2..f84a4083 100644
+index dd255fb4..5dc0d860 100644
--- a/src/os/os_anyos_test.go
+++ b/src/os/os_anyos_test.go
@@ -277,6 +277,10 @@ func TestDirFS(t *testing.T) {
diff --git a/0006-Skip-broken-tests-on-i686.patch b/0006-Skip-broken-tests-on-i686.patch
index ea1071d..ac4d59f 100644
--- a/0006-Skip-broken-tests-on-i686.patch
+++ b/0006-Skip-broken-tests-on-i686.patch
@@ -1,7 +1,7 @@
-From c645a887a6989e0210c782bb84d4f31200e0d333 Mon Sep 17 00:00:00 2001
+From a44f31de099aaf6768af2102919f1a8c221ce6f4 Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sun, 8 May 2022 18:39:26 -0400
-Subject: [PATCH 06/11] Skip broken tests on i686
+Subject: [PATCH 6/6] Skip broken tests on i686
* compress/flate runs out of memory
* testing/fstest uses Seek, which is not implemented there
@@ -12,10 +12,10 @@ Signed-off-by: Elliott Sales de Andrade
<quantum.analyst(a)gmail.com>
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
-index 60a5a574..cd3cb2f2 100644
+index 99f67c29..1ef11d29 100644
--- a/Makefile
+++ b/Makefile
-@@ -328,7 +328,6 @@ TEST_PACKAGES_FAST = \
+@@ -338,15 +338,21 @@ endif
# Additional standard library packages that pass tests on individual platforms
TEST_PACKAGES_LINUX := \
archive/zip \
@@ -23,8 +23,7 @@ index 60a5a574..cd3cb2f2 100644
compress/lzw \
crypto/hmac \
debug/dwarf \
-@@ -336,8 +335,15 @@ TEST_PACKAGES_LINUX := \
- io/fs \
+ debug/plan9obj \
io/ioutil \
strconv \
- testing/fstest \
diff --git a/0008-Temporarily-skip-io-fs-tests.patch
b/0008-Temporarily-skip-io-fs-tests.patch
deleted file mode 100644
index 6f1c08a..0000000
--- a/0008-Temporarily-skip-io-fs-tests.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 7715588992ca3bd6495fff544a584b2708b1a3f4 Mon Sep 17 00:00:00 2001
-From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
-Date: Thu, 21 Jul 2022 02:06:53 -0400
-Subject: [PATCH 08/11] Temporarily skip io/fs tests
-
-Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
----
- Makefile | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index cd3cb2f2..ff59e5e6 100644
---- a/Makefile
-+++ b/Makefile
-@@ -332,7 +332,6 @@ TEST_PACKAGES_LINUX := \
- crypto/hmac \
- debug/dwarf \
- debug/plan9obj \
-- io/fs \
- io/ioutil \
- strconv \
- text/template/parse
---
-2.36.1
-
diff --git a/0009-Add-ErrProcessDone-error.patch b/0009-Add-ErrProcessDone-error.patch
deleted file mode 100644
index 691f13f..0000000
--- a/0009-Add-ErrProcessDone-error.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 08a9276d4c9140545c5238cc3b9c7e20eadb5f97 Mon Sep 17 00:00:00 2001
-From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
-Date: Sat, 6 Aug 2022 16:53:48 -0400
-Subject: [PATCH 09/11] Add ErrProcessDone error
-
-This is used in upstream Go's `os` package now.
-
-Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
----
- src/os/exec.go | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/src/os/exec.go b/src/os/exec.go
-index 030979b2..a80c4316 100644
---- a/src/os/exec.go
-+++ b/src/os/exec.go
-@@ -1,6 +1,9 @@
- package os
-
--import "syscall"
-+import (
-+ "errors"
-+ "syscall"
-+)
-
- type Signal interface {
- String() string
-@@ -24,6 +27,9 @@ type ProcAttr struct {
- Sys *syscall.SysProcAttr
- }
-
-+// ErrProcessDone indicates a Process has finished.
-+var ErrProcessDone = errors.New("os: process already finished")
-+
- type ProcessState struct {
- }
-
---
-2.36.1
-
diff --git a/0010-Fix-tinygo-test-with-Go-1.19.patch
b/0010-Fix-tinygo-test-with-Go-1.19.patch
deleted file mode 100644
index 97cb453..0000000
--- a/0010-Fix-tinygo-test-with-Go-1.19.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 246a99fa9991743651f3e518b873e2ab9b20e575 Mon Sep 17 00:00:00 2001
-From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
-Date: Sat, 6 Aug 2022 17:25:56 -0400
-Subject: [PATCH 10/11] Fix tinygo-test with Go 1.19
-
-One of the internal packages used for tests was moved in that version.
-
-Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
----
- Makefile | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index ff59e5e6..6876dbb5 100644
---- a/Makefile
-+++ b/Makefile
-@@ -280,7 +280,6 @@ TEST_PACKAGES_FAST = \
- container/list \
- container/ring \
- crypto/des \
-- crypto/elliptic/internal/fiat \
- crypto/internal/subtle \
- crypto/md5 \
- crypto/rc4 \
-@@ -317,6 +316,14 @@ TEST_PACKAGES_FAST = \
- unicode \
- unicode/utf16 \
- unicode/utf8 \
-+ $(nil)
-+
-+# Assume this will go away before Go2, so only check minor version.
-+ifeq ($(filter $(shell $(GO) env GOVERSION | cut -f 2 -d.), 16 17 18), )
-+TEST_PACKAGES_FAST += crypto/internal/nistec/fiat
-+else
-+TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
-+endif
-
- # archive/zip requires os.ReadAt, which is not yet supported on windows
- # debug/plan9obj requires os.ReadAt, which is not yet supported on windows
---
-2.36.1
-
diff --git a/0011-Fix-tinygo-test-with-Go-1.16.patch
b/0011-Fix-tinygo-test-with-Go-1.16.patch
deleted file mode 100644
index e9791ef..0000000
--- a/0011-Fix-tinygo-test-with-Go-1.16.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 55856a4dc32934077fb50c9536c33f0eaa0e74cb Mon Sep 17 00:00:00 2001
-From: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
-Date: Sun, 7 Aug 2022 01:06:32 -0400
-Subject: [PATCH 11/11] Fix tinygo-test with Go 1.16
-
-Some of these packages were only added in 1.17
-
-Signed-off-by: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
----
- Makefile | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index 6876dbb5..3bf6e614 100644
---- a/Makefile
-+++ b/Makefile
-@@ -304,7 +304,6 @@ TEST_PACKAGES_FAST = \
- math \
- math/cmplx \
- net \
-- net/http/internal/ascii \
- net/mail \
- os \
- path \
-@@ -319,11 +318,17 @@ TEST_PACKAGES_FAST = \
- $(nil)
-
- # Assume this will go away before Go2, so only check minor version.
--ifeq ($(filter $(shell $(GO) env GOVERSION | cut -f 2 -d.), 16 17 18), )
-+GO_MINOR_VERSION := $(shell $(GO) env GOVERSION | cut -f 2 -d.)
-+# Added in Go 1.17.
-+ifeq ($(filter $(GO_MINOR_VERSION), 16), )
-+TEST_PACKAGES_FAST += net/http/internal/ascii
-+ifeq ($(filter $(GO_MINOR_VERSION), 16 17 18), )
-+# Renamed fiat in Go 1.19.
- TEST_PACKAGES_FAST += crypto/internal/nistec/fiat
- else
- TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
- endif
-+endif
-
- # archive/zip requires os.ReadAt, which is not yet supported on windows
- # debug/plan9obj requires os.ReadAt, which is not yet supported on windows
---
-2.36.1
-
diff --git a/sources b/sources
index c2fdadb..4597e0f 100644
--- a/sources
+++ b/sources
@@ -1,4 +1,4 @@
-SHA512 (tinygo-0.25.0.tar.gz) =
ec3d7e930f1b1aba79d506f236dc2da4ea0b693167eadb9fe36036da62135a468d6c0be3fe8cd4d888a051219107b86e4a2e79ebddcd0af823bb94281832c1b6
+SHA512 (tinygo-0.26.0.tar.gz) =
7b95f6b4356545b806207092fa315863446227e3f90d05abad1f231b381d402b00654e11ab79472c32d5572ea7183bdd4e5ee34190a13e3aefa668ebcd1042b4
SHA512 (avr-6624554c02b237b23dc17d53e992bf54033fc228.tar.gz) =
1aa157bd761db38f8680614fa1cf47d7009508f65291b7eaaa5aba1ae76d35103f68a42947b7269a170d2f1cf8fb09941a5d74070fe6d204b68dd15a9ad2ed29
SHA512 (cmsis-9fe411cef1cef5de58e5957b89760759de44e393-clean.tar.xz) =
f131fc241f61982c49f334eb502c2f13da61eb7bdaa641ee84a8de30c4d576b735b8aadeafd7d75351473a2df6a42de6a236ecc5dcc616ee6cfcc07af29446f9
SHA512 (cmsis_svd-df75ff974c76a911fc2815e29807f5ecaae06fc2-clean.tar.xz) =
8abbc6f366aed9571a74a4b6e7065ed2d6a59e0495c3745681d9a654d61edd136319788741f7afc781211adb64ed1faeafe9d6acc6be5a16d9ee48e98c5ddeb1
diff --git a/tinygo.spec b/tinygo.spec
index d8fcbd9..e228822 100644
--- a/tinygo.spec
+++ b/tinygo.spec
@@ -6,15 +6,11 @@
#
https://github.com/tinygo-org/tinygo
%global goipath
github.com/tinygo-org/tinygo
-Version: 0.25.0
+Version: 0.26.0
%global CMSIS_commit 9fe411cef1cef5de58e5957b89760759de44e393
%global avr_commit 6624554c02b237b23dc17d53e992bf54033fc228
-%if %{fedora} > 35
%global clang_llvm_version 14
-%else
-%global clang_llvm_version 13
-%endif
%global cmsis_svd_commit df75ff974c76a911fc2815e29807f5ecaae06fc2
%global compiler_rt_version %{clang_llvm_version}.0.0
%global macos_minsdk_commit ebb736fda2bec7cea38dcda807518b835a539525
@@ -83,33 +79,24 @@ Patch0004:
0004-Suggest-optional-packages-to-install-if-missing.patch
Patch0005: 0005-Skip-TestDirFS-on-32-bit-systems.patch
Patch0006: 0006-Skip-broken-tests-on-i686.patch
-#
https://github.com/tinygo-org/tinygo/issues/3008
-# Broken due to TestCVE202230630
-Patch0008: 0008-Temporarily-skip-io-fs-tests.patch
-
-#
https://github.com/tinygo-org/tinygo/pull/3060
-Patch0009: 0009-Add-ErrProcessDone-error.patch
-Patch0010: 0010-Fix-tinygo-test-with-Go-1.19.patch
-Patch0011: 0011-Fix-tinygo-test-with-Go-1.16.patch
-
# Not supported upstream yet.
ExcludeArch: armv7hl ppc64le s390x
BuildRequires: (clang-devel >= %{clang_llvm_version} with clang-devel < %{lua:
print(tonumber(rpm.expand('%{clang_llvm_version}')) + 1)})
BuildRequires:
golang(github.com/aykevl/go-wasm)
BuildRequires:
golang(github.com/blakesmith/ar)
-%if %{fedora} > 35
%ifnarch %{ix86}
BuildRequires: chromium
BuildRequires:
golang(github.com/chromedp/chromedp) >= 0.7.6
BuildRequires:
golang(github.com/chromedp/cdproto/cdp)
%endif
-%endif
BuildRequires:
golang(github.com/gofrs/flock) >= 0.8.1
BuildRequires:
golang(github.com/google/shlex)
+BuildRequires:
golang(github.com/inhies/go-bytesize)
BuildRequires:
golang(github.com/marcinbor85/gohex)
BuildRequires:
golang(github.com/mattn/go-colorable) >= 0.1.8
-BuildRequires: golang(go.bug.st/serial) >= 1.1.2
+BuildRequires:
golang(github.com/mattn/go-tty) >= 0.0.4
+BuildRequires: golang(go.bug.st/serial) >= 1.3.5
BuildRequires:
golang(golang.org/x/tools/go/ast/astutil)
BuildRequires:
golang(golang.org/x/tools/go/ssa) >= 0.1.11
BuildRequires: golang(gopkg.in/yaml.v2) >= 2.4.0
@@ -264,6 +251,7 @@ cp -rp lib/musl/src/internal %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/legacy %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/malloc %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/mman %{buildroot}%{tinygoroot}/lib/musl/src
+cp -rp lib/musl/src/math %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/signal %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/stdio %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/string %{buildroot}%{tinygoroot}/lib/musl/src
@@ -284,6 +272,7 @@ cp -rp lib/picolibc/newlib/libc/tinystdio
%{buildroot}%{tinygoroot}/lib/picolibc
chmod -x %{buildroot}%{tinygoroot}/lib/picolibc/newlib/libc/tinystdio/make-dtoa-data
install -vdm 0755 %{buildroot}%{tinygoroot}/lib/picolibc/newlib/libm
cp -rp lib/picolibc/newlib/libm/common
%{buildroot}%{tinygoroot}/lib/picolibc/newlib/libm
+cp -rp lib/picolibc/newlib/libm/math %{buildroot}%{tinygoroot}/lib/picolibc/newlib/libm
cp -rp lib/picolibc-stdio.c %{buildroot}%{tinygoroot}/lib
install -vdm 0755 %{buildroot}%{tinygoroot}/pkg
for target in thumbv6m-unknown-unknown-eabi-cortex-m0
thumbv6m-unknown-unknown-eabi-cortex-m0plus thumbv7em-unknown-unknown-eabi-cortex-m4; do
@@ -307,11 +296,9 @@ export GO111MODULE=off
export XDG_CACHE_HOME="${PWD}/$(mktemp -d tinygo.XXXXXX)"
%gocheck -v -t src -t tests
( cd _build/src/%{goipath} && GOPATH=%{currentgosourcedir}/_build:$GOPATH make
smoketest STM32=0 XTENSA=0 )
-%if %{fedora} > 35
%ifnarch %{ix86} aarch64
make wasmtest
%endif
-%endif
# Ignoring errors due to CGo issue:
#
https://github.com/tinygo-org/tinygo/issues/3057
%ifarch %{ix86}
commit 544baed7e0bae83a4ef2b7ee622bdfccff305860
Author: Elliott Sales de Andrade <quantum.analyst(a)gmail.com>
Date: Sat Oct 8 23:30:40 2022 -0400
Fix missing musl directory
See
https://github.com/tinygo-org/tinygo/issues/3057
diff --git a/tinygo.spec b/tinygo.spec
index 434ec2d..d8fcbd9 100644
--- a/tinygo.spec
+++ b/tinygo.spec
@@ -261,6 +261,7 @@ cp -rp lib/musl/src/errno %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/exit %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/include %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/internal %{buildroot}%{tinygoroot}/lib/musl/src
+cp -rp lib/musl/src/legacy %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/malloc %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/mman %{buildroot}%{tinygoroot}/lib/musl/src
cp -rp lib/musl/src/signal %{buildroot}%{tinygoroot}/lib/musl/src
@@ -314,9 +315,9 @@ make wasmtest
# Ignoring errors due to CGo issue:
#
https://github.com/tinygo-org/tinygo/issues/3057
%ifarch %{ix86}
-make tinygo-test-fast || true
+make tinygo-test-fast
%else
-make tinygo-test || true
+make tinygo-test
%endif
%endif