Compare commits

...

2 Commits

Author SHA1 Message Date
Ayke van Laethem 89ffb47a0c wasm: add recover support
Add unwinding and recover support for wasm using WebAssembly exception
handling. This still has a few gotchas:

  * Many WASI systems don't support exception handling yet.
    For example, see:
    https://github.com/bytecodealliance/wasmtime/issues/2049
  * Asyncify doesn't support wasm exception handling:
    https://github.com/WebAssembly/binaryen/issues/4470
    This means it's not possible to use goroutines together with
    panic/recover.
  * The current way that exceptions are implemented pretend to be C++
    exceptions, but work slightly differently. If C++ code is called
    (for example through CGo) that raises an exception, that exception
    will be eaten by TinyGo and not be propagated. This is fixable, it
    just hasn't been implemented (because we don't actually support C++
    right now).

I hope that these issues will be resolved over time. At least for now,
people who need `recover()` have a way to use it.
2024-08-14 14:22:37 +02:00
Ayke van Laethem 2f7952ff29 compiler: support panics inside indirect deferred functions
Found this bug while working on WebAssembly recover support.
2024-08-14 14:20:44 +02:00
30 changed files with 918 additions and 397 deletions
+1
View File
@@ -747,6 +747,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
} }
ldflags = append(ldflags, "-mllvm", "-mcpu="+config.CPU()) ldflags = append(ldflags, "-mllvm", "-mcpu="+config.CPU())
ldflags = append(ldflags, "-mllvm", "-mattr="+config.Features()) // needed for MIPS softfloat ldflags = append(ldflags, "-mllvm", "-mattr="+config.Features()) // needed for MIPS softfloat
ldflags = append(ldflags, "-mllvm", "-wasm-enable-eh")
if config.GOOS() == "windows" { if config.GOOS() == "windows" {
// Options for the MinGW wrapper for the lld COFF linker. // Options for the MinGW wrapper for the lld COFF linker.
ldflags = append(ldflags, ldflags = append(ldflags,
+23 -8
View File
@@ -70,21 +70,25 @@ func (b *builder) createRuntimeInvoke(fnName string, args []llvm.Value, name str
// createCall creates a call to the given function with the arguments possibly // createCall creates a call to the given function with the arguments possibly
// expanded. // expanded.
func (b *builder) createCall(fnType llvm.Type, 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)) return b.CreateCall(fnType, fn, b.expandFormalParams(args), name)
for _, arg := range args {
fragments := b.expandFormalParam(arg)
expanded = append(expanded, fragments...)
}
return b.CreateCall(fnType, fn, expanded, name)
} }
// createInvoke is like createCall but continues execution at the landing pad if // createInvoke is like createCall but continues execution at the landing pad if
// the call resulted in a panic. // the call resulted in a panic.
func (b *builder) createInvoke(fnType llvm.Type, 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() { switch b.deferFrameType() {
case recoverInlineAsm:
b.createInvokeCheckpoint() b.createInvokeCheckpoint()
return b.createCall(fnType, fn, args, name)
case recoverWasmEH:
continueBB := b.insertBasicBlock("invoke.cont")
call := b.CreateInvoke(fnType, fn, b.expandFormalParams(args), continueBB, b.landingpad, name)
b.SetInsertPointAtEnd(continueBB)
b.blockExits[b.currentBlock] = continueBB
return call
default:
return b.createCall(fnType, 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 // Expand an argument type to a list that can be used in a function call
@@ -123,6 +127,17 @@ func (b *builder) expandFormalParamOffsets(t llvm.Type) []uint64 {
} }
} }
// expandFormalParams expands every param in the params slice like
// expandFormalParam.
func (b *builder) expandFormalParams(params []llvm.Value) []llvm.Value {
expanded := make([]llvm.Value, 0, len(params))
for _, arg := range params {
fragments := b.expandFormalParam(arg)
expanded = append(expanded, fragments...)
}
return expanded
}
// expandFormalParam splits a formal param value into pieces, so it can be // expandFormalParam splits a formal param value into pieces, so it can be
// passed directly as part of a function call. For example, it splits up small // passed directly as part of a function call. For example, it splits up small
// structs into individual fields. It is the equivalent of expandFormalParamType // structs into individual fields. It is the equivalent of expandFormalParamType
+13 -10
View File
@@ -355,7 +355,10 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
} }
func (c *compilerContext) getRuntimeType(name string) types.Type { func (c *compilerContext) getRuntimeType(name string) types.Type {
return c.runtimePkg.Scope().Lookup(name).(*types.TypeName).Type() if typ, ok := c.runtimePkg.Scope().Lookup(name).(*types.TypeName); ok {
return typ.Type()
}
panic("runtime type not found: " + name)
} }
// getLLVMRuntimeType obtains a named type from the runtime package and returns // getLLVMRuntimeType obtains a named type from the runtime package and returns
@@ -1350,7 +1353,7 @@ func (b *builder) createFunction() {
b.CreateBr(b.afterDefersBlock[i]) b.CreateBr(b.afterDefersBlock[i])
} }
if b.hasDeferFrame() { if b.deferFrameType() != recoverNone {
// Create the landing pad block, where execution continues after a // Create the landing pad block, where execution continues after a
// panic. // panic.
b.createLandingPad() b.createLandingPad()
@@ -1487,8 +1490,11 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
b.createRuntimeInvoke("_panic", []llvm.Value{value}, "") b.createRuntimeInvoke("_panic", []llvm.Value{value}, "")
b.CreateUnreachable() b.CreateUnreachable()
case *ssa.Return: case *ssa.Return:
if b.hasDeferFrame() { switch b.deferFrameType() {
b.createRuntimeCall("destroyDeferFrame", []llvm.Value{b.deferFrame}, "") case recoverInlineAsm:
b.createRuntimeCall("destroyDeferFrameInlineAsm", []llvm.Value{b.deferFrame}, "")
case recoverWasmEH:
b.createRuntimeCall("destroyDeferFrameWasmEH", []llvm.Value{b.deferFrame}, "")
} }
if len(instr.Results) == 0 { if len(instr.Results) == 0 {
b.CreateRetVoid() b.CreateRetVoid()
@@ -1741,7 +1747,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
return b.CreateExtractValue(cplx, 0, "real"), nil return b.CreateExtractValue(cplx, 0, "real"), nil
case "recover": case "recover":
useParentFrame := uint64(0) useParentFrame := uint64(0)
if b.hasDeferFrame() { if b.fn.Recover != nil {
// recover() should return the panic value of the parent function, // recover() should return the panic value of the parent function,
// not of the current function. // not of the current function.
useParentFrame = 1 useParentFrame = 1
@@ -1851,11 +1857,8 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"): case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
return b.createRawSyscallNoError(instr) return b.createRawSyscallNoError(instr)
case name == "runtime.supportsRecover": case name == "runtime.supportsRecover":
supportsRecover := uint64(0) supportsRecover := uint64(b.supportsRecover())
if b.supportsRecover() { return llvm.ConstInt(b.ctx.Int8Type(), supportsRecover, false), nil
supportsRecover = 1
}
return llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil
case name == "runtime.panicStrategy": case name == "runtime.panicStrategy":
// These constants are defined in src/runtime/panic.go. // These constants are defined in src/runtime/panic.go.
panicStrategy := map[string]uint64{ panicStrategy := map[string]uint64{
+1
View File
@@ -44,6 +44,7 @@ func TestCompiler(t *testing.T) {
{"interface.go", "", ""}, {"interface.go", "", ""},
{"func.go", "", ""}, {"func.go", "", ""},
{"defer.go", "cortex-m-qemu", ""}, {"defer.go", "cortex-m-qemu", ""},
{"defer.go", "wasm", "none"},
{"pragma.go", "", ""}, {"pragma.go", "", ""},
{"goroutine.go", "wasm", "asyncify"}, {"goroutine.go", "wasm", "asyncify"},
{"goroutine.go", "cortex-m-qemu", "tasks"}, {"goroutine.go", "cortex-m-qemu", "tasks"},
+137 -34
View File
@@ -16,34 +16,54 @@ package compiler
import ( import (
"go/types" "go/types"
"strconv" "strconv"
"strings"
"github.com/tinygo-org/tinygo/compiler/llvmutil" "github.com/tinygo-org/tinygo/compiler/llvmutil"
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
) )
type recoverType uint8
const (
// Note: this matches recoverSupport in src/runtime/panic.go
recoverNone recoverType = iota
recoverInlineAsm
recoverWasmEH // WebAssembly exception handling
)
// supportsRecover returns whether the compiler supports the recover() builtin // supportsRecover returns whether the compiler supports the recover() builtin
// for the current architecture. // for the current architecture.
func (b *builder) supportsRecover() bool { func (c *compilerContext) supportsRecover() recoverType {
switch b.archFamily() { switch c.archFamily() {
case "wasm32": case "wasm32":
// Probably needs to be implemented using the exception handling if !strings.Contains(c.Features, "+exception-handling") {
// proposal of WebAssembly: // No support for the exception handling proposal.
// https://github.com/WebAssembly/exception-handling return recoverNone
return false }
if c.Scheduler == "asyncify" {
// Asyncify does not support WebAssembly exception handling.
// It exits with the following message:
// unexpected expression type
// UNREACHABLE executed at $TINYGOROOT/lib/binaryen/src/passes/Asyncify.cpp:1142!
// See: https://github.com/WebAssembly/binaryen/issues/4470
return recoverNone
}
// Use WebAssembly exception handling.
return recoverWasmEH
case "riscv64", "xtensa": case "riscv64", "xtensa":
// TODO: add support for these architectures // TODO: add support for these architectures
return false return recoverNone
default: default:
return true return recoverInlineAsm
} }
} }
// hasDeferFrame returns whether the current function needs to catch panics and // deferFrameType returns the defer type for this function. It is always
// run defers. // recoverNone for functions without defer.
func (b *builder) hasDeferFrame() bool { func (b *builder) deferFrameType() recoverType {
if b.fn.Recover == nil { if b.fn.Recover == nil {
return false return recoverNone
} }
return b.supportsRecover() return b.supportsRecover()
} }
@@ -63,21 +83,40 @@ func (b *builder) deferInitFunc() {
b.deferPtr = b.CreateAlloca(b.dataPtrType, "deferPtr") b.deferPtr = b.CreateAlloca(b.dataPtrType, "deferPtr")
b.CreateStore(llvm.ConstPointerNull(b.dataPtrType), b.deferPtr) b.CreateStore(llvm.ConstPointerNull(b.dataPtrType), b.deferPtr)
if b.hasDeferFrame() { switch b.deferFrameType() {
case recoverInlineAsm:
// Set up the defer frame with the current stack pointer. // Set up the defer frame with the current stack pointer.
// This assumes that the stack pointer doesn't move outside of the // This assumes that the stack pointer doesn't move outside of the
// function prologue/epilogue (an invariant maintained by TinyGo but // function prologue/epilogue (an invariant maintained by TinyGo but
// possibly broken by the C alloca function). // possibly broken by the C alloca function).
// The frame pointer is _not_ saved, because it is marked as clobbered // The frame pointer is _not_ saved, because it is marked as clobbered
// in the setjmp-like inline assembly. // in the setjmp-like inline assembly.
deferFrameType := b.getLLVMRuntimeType("deferFrame") deferFrameType := b.getLLVMRuntimeType("deferFrameInlineAsm")
b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf") b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf")
stackPointer := b.readStackPointer() stackPointer := b.readStackPointer()
b.createRuntimeCall("setupDeferFrame", []llvm.Value{b.deferFrame, stackPointer}, "") b.createRuntimeCall("setupDeferFrameInlineAsm", []llvm.Value{b.deferFrame, stackPointer}, "")
// Create the landing pad block, which is where control transfers after // Create the landing pad block, which is where control transfers after
// a panic. // a panic.
b.landingpad = b.ctx.AddBasicBlock(b.llvmFn, "lpad") b.landingpad = b.ctx.AddBasicBlock(b.llvmFn, "lpad")
case recoverWasmEH:
// Set a personality function, which is required by LLVM but not
// actually called. __gxx_wasm_personality_v0 is the only one that is
// acceptable to the WebAssembly backend it seems.
personality := b.mod.NamedFunction("__gxx_wasm_personality_v0")
if personality.IsNil() {
fnType := llvm.FunctionType(b.ctx.Int32Type(), nil, true)
personality = llvm.AddFunction(b.mod, "__gxx_wasm_personality_v0", fnType)
}
b.llvmFn.SetPersonality(personality)
// Set up the defer frame.
deferFrameType := b.getLLVMRuntimeType("deferFrameWasmEH")
b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf")
b.createRuntimeCall("setupDeferFrameWasmEH", []llvm.Value{b.deferFrame}, "")
// Create the landing pad where the 'throw' instruction will jump to.
b.landingpad = b.ctx.AddBasicBlock(b.llvmFn, "catch.dispatch")
} }
} }
@@ -95,6 +134,43 @@ func (b *builder) createLandingPad() {
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{}) b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
} }
if b.supportsRecover() == recoverWasmEH {
// Insert exception handling instructions.
// This emulates C++ exceptions, as if every function is wrapped like
// this:
//
// try {
// function body
// } catch (...) {
// run all defers
// }
// if deferFrame.Panicking {
// // re-raise the same panic message
// panic(previousPanic)
// }
//
// This means that if there is a C++ exception in the program, it will
// get eaten by the Go code. This is fixable if needed (by checking
// whether it's actually a TinyGo exception and re-raising the same
// exception if it isn't after running deferred functions).
// For more information about C++ exception support in WebAssembly:
// https://github.com/WebAssembly/tool-conventions/blob/main/EHScheme.md
// basic block: catch.dispatch
catchStartBB := b.insertBasicBlock("catch.start")
catchswitch := b.CreateCatchSwitch(llvm.Value{}, llvm.BasicBlock{}, 1, "")
catchswitch.AddHandler(catchStartBB)
// basic block: catch.start
b.SetInsertPointAtEnd(catchStartBB)
catchpad := b.CreateCatchPad(catchswitch, []llvm.Value{llvm.ConstNull(b.dataPtrType)}, "")
rundefersBB := b.insertBasicBlock("rundefers")
b.CreateCatchRet(catchpad, rundefersBB)
// basic block: rundefers
b.SetInsertPointAtEnd(rundefersBB)
}
b.createRunDefers() b.createRunDefers()
// Continue at the 'recover' block, which returns to the parent in an // Continue at the 'recover' block, which returns to the parent in an
@@ -432,11 +508,25 @@ func (b *builder) createRunDefers() {
// } // }
// } // }
// Create loop, in the order: loophead, loop, callback0, callback1, ..., unreachable, end. // Create loop, in the order:
// - loophead
// - loop
// - callback0
// - callback1
// - callback*
// - unreachable
// - catch.dispatch (if wasm EH)
// - catch.start (if wasm EH)
// - end
var catchDispatch, catchStart llvm.BasicBlock
end := b.insertBasicBlock("rundefers.end") end := b.insertBasicBlock("rundefers.end")
unreachable := b.ctx.InsertBasicBlock(end, "rundefers.default") unreachable := b.ctx.InsertBasicBlock(end, "rundefers.default")
loop := b.ctx.InsertBasicBlock(unreachable, "rundefers.loop") loop := b.ctx.InsertBasicBlock(unreachable, "rundefers.loop")
loophead := b.ctx.InsertBasicBlock(loop, "rundefers.loophead") loophead := b.ctx.InsertBasicBlock(loop, "rundefers.loophead")
if b.supportsRecover() == recoverWasmEH {
catchDispatch = b.ctx.InsertBasicBlock(end, "rundefers.catch.dispatch")
catchStart = b.ctx.InsertBasicBlock(end, "rundefers.catch.start")
}
b.CreateBr(loophead) b.CreateBr(loophead)
// Create loop head: // Create loop head:
@@ -471,6 +561,9 @@ func (b *builder) createRunDefers() {
block := b.insertBasicBlock("rundefers.callback" + strconv.Itoa(i)) block := b.insertBasicBlock("rundefers.callback" + strconv.Itoa(i))
sw.AddCase(llvm.ConstInt(b.uintptrType, uint64(i), false), block) sw.AddCase(llvm.ConstInt(b.uintptrType, uint64(i), false), block)
b.SetInsertPointAtEnd(block) b.SetInsertPointAtEnd(block)
var fnType llvm.Type
var llvmFn llvm.Value
var forwardParams []llvm.Value
switch callback := callback.(type) { switch callback := callback.(type) {
case *ssa.CallCommon: case *ssa.CallCommon:
// Call on an value or interface value. // Call on an value or interface value.
@@ -491,7 +584,6 @@ func (b *builder) createRunDefers() {
} }
// Extract the params from the struct (including receiver). // Extract the params from the struct (including receiver).
forwardParams := []llvm.Value{}
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false) zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
deferredCallType := b.ctx.StructType(valueTypes, false) deferredCallType := b.ctx.StructType(valueTypes, false)
for i := 2; i < len(valueTypes); i++ { for i := 2; i < len(valueTypes); i++ {
@@ -500,9 +592,6 @@ func (b *builder) createRunDefers() {
forwardParams = append(forwardParams, forwardParam) forwardParams = append(forwardParams, forwardParam)
} }
var fnPtr llvm.Value
var fnType llvm.Type
if !callback.IsInvoke() { if !callback.IsInvoke() {
// Isolate the func value. // Isolate the func value.
funcValue := forwardParams[0] funcValue := forwardParams[0]
@@ -510,7 +599,7 @@ func (b *builder) createRunDefers() {
//Get function pointer and context //Get function pointer and context
var context llvm.Value var context llvm.Value
fnPtr, context = b.decodeFuncValue(funcValue) llvmFn, context = b.decodeFuncValue(funcValue)
fnType = b.getLLVMFunctionType(callback.Signature()) fnType = b.getLLVMFunctionType(callback.Signature())
//Pass context //Pass context
@@ -519,8 +608,8 @@ func (b *builder) createRunDefers() {
// Move typecode from the start to the end of the list of // Move typecode from the start to the end of the list of
// parameters. // parameters.
forwardParams = append(forwardParams[1:], forwardParams[0]) forwardParams = append(forwardParams[1:], forwardParams[0])
fnPtr = b.getInvokeFunction(callback) llvmFn = b.getInvokeFunction(callback)
fnType = fnPtr.GlobalValueType() fnType = llvmFn.GlobalValueType()
// Add the context parameter. An interface call cannot also be a // Add the context parameter. An interface call cannot also be a
// closure but we have to supply the parameter anyway for platforms // closure but we have to supply the parameter anyway for platforms
@@ -528,8 +617,6 @@ func (b *builder) createRunDefers() {
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType)) forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
} }
b.createCall(fnType, fnPtr, forwardParams, "")
case *ssa.Function: case *ssa.Function:
// Direct call. // Direct call.
@@ -541,7 +628,6 @@ func (b *builder) createRunDefers() {
deferredCallType := b.ctx.StructType(valueTypes, false) deferredCallType := b.ctx.StructType(valueTypes, false)
// Extract the params from the struct. // Extract the params from the struct.
forwardParams := []llvm.Value{}
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false) zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
for i := range getParams(callback.Signature) { for i := range getParams(callback.Signature) {
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep") gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
@@ -557,9 +643,7 @@ func (b *builder) createRunDefers() {
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType)) forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
} }
// Call real function. fnType, llvmFn = b.getFunction(callback)
fnType, fn := b.getFunction(callback)
b.createInvoke(fnType, fn, forwardParams, "")
case *ssa.MakeClosure: case *ssa.MakeClosure:
// Get the real defer struct type and cast to it. // Get the real defer struct type and cast to it.
@@ -573,7 +657,6 @@ func (b *builder) createRunDefers() {
deferredCallType := b.ctx.StructType(valueTypes, false) deferredCallType := b.ctx.StructType(valueTypes, false)
// Extract the params from the struct. // Extract the params from the struct.
forwardParams := []llvm.Value{}
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false) zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
for i := 2; i < len(valueTypes); i++ { for i := 2; i < len(valueTypes); i++ {
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "") gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
@@ -582,8 +665,7 @@ func (b *builder) createRunDefers() {
} }
// Call deferred function. // Call deferred function.
fnType, llvmFn := b.getFunction(fn) fnType, llvmFn = b.getFunction(fn)
b.createCall(fnType, llvmFn, forwardParams, "")
case *ssa.Builtin: case *ssa.Builtin:
db := b.deferBuiltinFuncs[callback] db := b.deferBuiltinFuncs[callback]
@@ -611,12 +693,20 @@ func (b *builder) createRunDefers() {
if err != nil { if err != nil {
b.diagnostics = append(b.diagnostics, err) b.diagnostics = append(b.diagnostics, err)
} }
b.CreateBr(loophead)
continue
default: default:
panic("unknown deferred function type") panic("unknown deferred function type")
} }
// Branch back to the start of the loop. // Call the deferred function.
b.CreateBr(loophead) if b.supportsRecover() == recoverWasmEH {
b.CreateInvoke(fnType, llvmFn, b.expandFormalParams(forwardParams), loophead, catchDispatch, "")
} else {
b.createInvoke(fnType, llvmFn, forwardParams, "")
// Branch back to the start of the loop.
b.CreateBr(loophead)
}
} }
// Create default unreachable block: // Create default unreachable block:
@@ -626,6 +716,19 @@ func (b *builder) createRunDefers() {
b.SetInsertPointAtEnd(unreachable) b.SetInsertPointAtEnd(unreachable)
b.CreateUnreachable() b.CreateUnreachable()
// Ignore any exception that might have occured while running the deferred
// functions. The compiler will insert a check whether the function is still
// panicking before return, so no panic gets lost.
if b.supportsRecover() == recoverWasmEH {
b.SetInsertPointAtEnd(catchDispatch)
catchswitch := b.CreateCatchSwitch(llvm.Value{}, llvm.BasicBlock{}, 1, "")
catchswitch.AddHandler(catchStart)
b.SetInsertPointAtEnd(catchStart)
catchpad := b.CreateCatchPad(catchswitch, []llvm.Value{llvm.ConstNull(b.dataPtrType)}, "")
b.CreateCatchRet(catchpad, loophead)
}
// End of loop. // End of loop.
b.SetInsertPointAtEnd(end) b.SetInsertPointAtEnd(end)
} }
+4 -1
View File
@@ -174,6 +174,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
// that the only thing we'll do is read the pointer. // that the only thing we'll do is read the pointer.
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0)) llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0))
case "__mulsi3", "__divmodsi4", "__udivmodsi4": case "__mulsi3", "__divmodsi4", "__udivmodsi4":
if strings.Split(c.Triple, "-")[0] == "avr" { if strings.Split(c.Triple, "-")[0] == "avr" {
// These functions are compiler-rt/libgcc functions that are // These functions are compiler-rt/libgcc functions that are
@@ -470,7 +471,9 @@ func (c *compilerContext) addStandardDefinedAttributes(llvmFn llvm.Value) {
// This behavior matches Clang when compiling C source files. // This behavior matches Clang when compiling C source files.
// It reduces binary size on Linux a little bit on non-x86_64 targets by // It reduces binary size on Linux a little bit on non-x86_64 targets by
// eliminating exception tables for these functions. // eliminating exception tables for these functions.
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0)) if c.supportsRecover() != recoverWasmEH {
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0))
}
if strings.Split(c.Triple, "-")[0] == "x86_64" { if strings.Split(c.Triple, "-")[0] == "x86_64" {
// Required by the ABI. // Required by the ABI.
// The uwtable has two possible values: sync (1) or async (2). We use // The uwtable has two possible values: sync (1) or async (2). We use
+25 -24
View File
@@ -13,30 +13,31 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.addInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 { define hidden i32 @main.addInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = add i32 %x, %y %0 = add i32 %x, %y
ret i32 %0 ret i32 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.equalInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 { define hidden i1 @main.equalInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %x, %y %0 = icmp eq i32 %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.divInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 { define hidden i32 @main.divInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@@ -54,10 +55,10 @@ divbyzero.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.divideByZeroPanic(ptr) #1 declare void @runtime.divideByZeroPanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.divUint(i32 %x, i32 %y, ptr %context) unnamed_addr #2 { define hidden i32 @main.divUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@@ -72,7 +73,7 @@ divbyzero.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.remInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 { define hidden i32 @main.remInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@@ -91,7 +92,7 @@ divbyzero.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.remUint(i32 %x, i32 %y, ptr %context) unnamed_addr #2 { define hidden i32 @main.remUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq i32 %y, 0 %0 = icmp eq i32 %y, 0
br i1 %0, label %divbyzero.throw, label %divbyzero.next br i1 %0, label %divbyzero.throw, label %divbyzero.next
@@ -106,61 +107,61 @@ divbyzero.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatEQ(float %x, float %y, ptr %context) unnamed_addr #2 { define hidden i1 @main.floatEQ(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp oeq float %x, %y %0 = fcmp oeq float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatNE(float %x, float %y, ptr %context) unnamed_addr #2 { define hidden i1 @main.floatNE(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp une float %x, %y %0 = fcmp une float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatLower(float %x, float %y, ptr %context) unnamed_addr #2 { define hidden i1 @main.floatLower(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp olt float %x, %y %0 = fcmp olt float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatLowerEqual(float %x, float %y, ptr %context) unnamed_addr #2 { define hidden i1 @main.floatLowerEqual(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp ole float %x, %y %0 = fcmp ole float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatGreater(float %x, float %y, ptr %context) unnamed_addr #2 { define hidden i1 @main.floatGreater(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp ogt float %x, %y %0 = fcmp ogt float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.floatGreaterEqual(float %x, float %y, ptr %context) unnamed_addr #2 { define hidden i1 @main.floatGreaterEqual(float %x, float %y, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp oge float %x, %y %0 = fcmp oge float %x, %y
ret i1 %0 ret i1 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.complexReal(float %x.r, float %x.i, ptr %context) unnamed_addr #2 { define hidden float @main.complexReal(float %x.r, float %x.i, ptr %context) unnamed_addr #1 {
entry: entry:
ret float %x.r ret float %x.r
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.complexImag(float %x.r, float %x.i, ptr %context) unnamed_addr #2 { define hidden float @main.complexImag(float %x.r, float %x.i, ptr %context) unnamed_addr #1 {
entry: entry:
ret float %x.i ret float %x.i
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 { define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fadd float %x.r, %y.r %0 = fadd float %x.r, %y.r
%1 = fadd float %x.i, %y.i %1 = fadd float %x.i, %y.i
@@ -170,7 +171,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 { define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fsub float %x.r, %y.r %0 = fsub float %x.r, %y.r
%1 = fsub float %x.i, %y.i %1 = fsub float %x.i, %y.i
@@ -180,7 +181,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 { define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fmul float %x.r, %y.r %0 = fmul float %x.r, %y.r
%1 = fmul float %x.i, %y.i %1 = fmul float %x.i, %y.i
@@ -194,19 +195,19 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.foo(ptr %context) unnamed_addr #2 { define hidden void @main.foo(ptr %context) unnamed_addr #1 {
entry: entry:
call void @"main.foo$1"(%main.kv.0 zeroinitializer, ptr undef) call void @"main.foo$1"(%main.kv.0 zeroinitializer, ptr undef)
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.foo$1"(%main.kv.0 %b, ptr %context) unnamed_addr #2 { define internal void @"main.foo$1"(%main.kv.0 %b, ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+16 -15
View File
@@ -9,16 +9,17 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanIntSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 { define hidden void @main.chanIntSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
%chan.value = alloca i32, align 4 %chan.value = alloca i32, align 4
@@ -32,15 +33,15 @@ entry:
} }
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
declare void @runtime.chanSend(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #1 declare void @runtime.chanSend(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #3
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 { define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
%chan.value = alloca i32, align 4 %chan.value = alloca i32, align 4
@@ -52,10 +53,10 @@ entry:
ret void ret void
} }
declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #1 declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #3
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 { define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList) call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
@@ -65,7 +66,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 { define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.blockedList = alloca %runtime.channelBlockedList, align 8 %chan.blockedList = alloca %runtime.channelBlockedList, align 8
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList) call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
@@ -75,7 +76,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.selectZeroRecv(ptr dereferenceable_or_null(32) %ch1, ptr dereferenceable_or_null(32) %ch2, ptr %context) unnamed_addr #2 { define hidden void @main.selectZeroRecv(ptr dereferenceable_or_null(32) %ch1, ptr dereferenceable_or_null(32) %ch2, ptr %context) unnamed_addr #1 {
entry: entry:
%select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8 %select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8
%select.send.value = alloca i32, align 4 %select.send.value = alloca i32, align 4
@@ -105,10 +106,10 @@ select.body: ; preds = %select.next
br label %select.done br label %select.done
} }
declare { i32, i1 } @runtime.tryChanSelect(ptr, ptr, i32, i32, ptr) #1 declare { i32, i1 } @runtime.tryChanSelect(ptr, ptr, i32, i32, ptr) #3
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } attributes #3 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #4 = { nounwind } attributes #4 = { nounwind }
+11 -11
View File
@@ -3,7 +3,7 @@ source_filename = "defer.go"
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 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" target triple = "thumbv7m-unknown-unknown-eabi"
%runtime.deferFrame = type { ptr, ptr, [0 x ptr], ptr, i1, %runtime._interface } %runtime.deferFrameInlineAsm = type { ptr, ptr, [0 x ptr], ptr, i1, %runtime._interface }
%runtime._interface = type { ptr, ptr } %runtime._interface = type { ptr, ptr }
%runtime._defer = type { i32, ptr } %runtime._defer = type { i32, ptr }
@@ -24,9 +24,9 @@ entry:
%defer.alloca = alloca { i32, ptr }, align 4 %defer.alloca = alloca { i32, ptr }, align 4
%deferPtr = alloca ptr, align 4 %deferPtr = alloca ptr, align 4
store ptr null, ptr %deferPtr, align 4 store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrame, align 4 %deferframe.buf = alloca %runtime.deferFrameInlineAsm, align 4
%0 = call ptr @llvm.stacksave.p0() %0 = call ptr @llvm.stacksave.p0()
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4 call void @runtime.setupDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
store i32 0, ptr %defer.alloca, align 4 store i32 0, ptr %defer.alloca, align 4
%defer.alloca.repack15 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1 %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 null, ptr %defer.alloca.repack15, align 4
@@ -40,7 +40,7 @@ entry:
br label %rundefers.block br label %rundefers.block
rundefers.after: ; preds = %rundefers.end rundefers.after: ; preds = %rundefers.end
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4 call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
ret void ret void
rundefers.block: ; preds = %1 rundefers.block: ; preds = %1
@@ -76,7 +76,7 @@ rundefers.end: ; preds = %rundefers.loophead
br label %rundefers.after br label %rundefers.after
recover: ; preds = %rundefers.end3 recover: ; preds = %rundefers.end3
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4 call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
ret void ret void
lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry
@@ -115,9 +115,9 @@ rundefers.end3: ; preds = %rundefers.loophead6
; Function Attrs: nocallback nofree nosync nounwind willreturn ; Function Attrs: nocallback nofree nosync nounwind willreturn
declare ptr @llvm.stacksave.p0() #3 declare ptr @llvm.stacksave.p0() #3
declare void @runtime.setupDeferFrame(ptr dereferenceable_or_null(24), ptr, ptr) #2 declare void @runtime.setupDeferFrameInlineAsm(ptr dereferenceable_or_null(24), ptr, ptr) #2
declare void @runtime.destroyDeferFrame(ptr dereferenceable_or_null(24), ptr) #2 declare void @runtime.destroyDeferFrameInlineAsm(ptr dereferenceable_or_null(24), ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #1 { define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #1 {
@@ -135,9 +135,9 @@ entry:
%defer.alloca = alloca { i32, ptr }, align 4 %defer.alloca = alloca { i32, ptr }, align 4
%deferPtr = alloca ptr, align 4 %deferPtr = alloca ptr, align 4
store ptr null, ptr %deferPtr, align 4 store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrame, align 4 %deferframe.buf = alloca %runtime.deferFrameInlineAsm, align 4
%0 = call ptr @llvm.stacksave.p0() %0 = call ptr @llvm.stacksave.p0()
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4 call void @runtime.setupDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
store i32 0, ptr %defer.alloca, align 4 store i32 0, ptr %defer.alloca, align 4
%defer.alloca.repack22 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1 %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 null, ptr %defer.alloca.repack22, align 4
@@ -155,7 +155,7 @@ entry:
br label %rundefers.block br label %rundefers.block
rundefers.after: ; preds = %rundefers.end rundefers.after: ; preds = %rundefers.end
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4 call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
ret void ret void
rundefers.block: ; preds = %1 rundefers.block: ; preds = %1
@@ -201,7 +201,7 @@ rundefers.end: ; preds = %rundefers.loophead
br label %rundefers.after br label %rundefers.after
recover: ; preds = %rundefers.end7 recover: ; preds = %rundefers.end7
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4 call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
ret void ret void
lpad: ; preds = %rundefers.callback119, %rundefers.callback016, %rundefers.callback1, %rundefers.callback0, %entry lpad: ; preds = %rundefers.callback119, %rundefers.callback016, %rundefers.callback1, %rundefers.callback0, %entry
+273
View File
@@ -0,0 +1,273 @@
; ModuleID = 'defer.go'
source_filename = "defer.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.deferFrameWasmEH = type { ptr, i1, %runtime._interface }
%runtime._interface = type { ptr, ptr }
%runtime._defer = type { i32, ptr }
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
define hidden void @main.init(ptr %context) unnamed_addr #2 {
entry:
ret void
}
declare void @main.external(ptr) #2
define hidden void @main.deferSimple(ptr %context) unnamed_addr #2 personality ptr @__gxx_wasm_personality_v0 {
entry:
%defer.alloca = alloca { i32, ptr }, align 8
%deferPtr = alloca ptr, align 4
store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrameWasmEH, align 8
call void @runtime.setupDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
%stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr nonnull %defer.alloca, ptr nonnull %stackalloc, ptr undef)
store i32 0, ptr %defer.alloca, align 4
%defer.alloca.repack13 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
store ptr null, ptr %defer.alloca.repack13, align 4
store ptr %defer.alloca, ptr %deferPtr, align 4
invoke void @main.external(ptr undef)
to label %invoke.cont unwind label %catch.dispatch
invoke.cont: ; preds = %entry
br label %rundefers.block
rundefers.after: ; preds = %rundefers.end
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
ret void
rundefers.block: ; preds = %invoke.cont
br label %rundefers.loophead
rundefers.loophead: ; preds = %rundefers.catch.start, %rundefers.callback0, %rundefers.block
%0 = load ptr, ptr %deferPtr, align 4
%stackIsNil = icmp eq ptr %0, null
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds %runtime._defer, ptr %0, 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 %0, align 4
switch i32 %callback, label %rundefers.default [
i32 0, label %rundefers.callback0
]
rundefers.callback0: ; preds = %rundefers.loop
invoke void @"main.deferSimple$1"(ptr undef)
to label %rundefers.loophead unwind label %rundefers.catch.dispatch
rundefers.default: ; preds = %rundefers.loop
unreachable
rundefers.catch.dispatch: ; preds = %rundefers.callback0
%1 = catchswitch within none [label %rundefers.catch.start] unwind to caller
rundefers.catch.start: ; preds = %rundefers.catch.dispatch
%2 = catchpad within %1 [ptr null]
catchret from %2 to label %rundefers.loophead
rundefers.end: ; preds = %rundefers.loophead
br label %rundefers.after
recover: ; preds = %rundefers.end1
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
ret void
catch.dispatch: ; preds = %entry
%3 = catchswitch within none [label %catch.start] unwind to caller
catch.start: ; preds = %catch.dispatch
%4 = catchpad within %3 [ptr null]
catchret from %4 to label %rundefers
rundefers: ; preds = %catch.start
br label %rundefers.loophead4
rundefers.loophead4: ; preds = %rundefers.catch.start6, %rundefers.callback012, %rundefers
%5 = load ptr, ptr %deferPtr, align 4
%stackIsNil7 = icmp eq ptr %5, null
br i1 %stackIsNil7, label %rundefers.end1, label %rundefers.loop3
rundefers.loop3: ; preds = %rundefers.loophead4
%stack.next.gep8 = getelementptr inbounds %runtime._defer, ptr %5, 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 %5, align 4
switch i32 %callback11, label %rundefers.default2 [
i32 0, label %rundefers.callback012
]
rundefers.callback012: ; preds = %rundefers.loop3
invoke void @"main.deferSimple$1"(ptr undef)
to label %rundefers.loophead4 unwind label %rundefers.catch.dispatch5
rundefers.default2: ; preds = %rundefers.loop3
unreachable
rundefers.catch.dispatch5: ; preds = %rundefers.callback012
%6 = catchswitch within none [label %rundefers.catch.start6] unwind to caller
rundefers.catch.start6: ; preds = %rundefers.catch.dispatch5
%7 = catchpad within %6 [ptr null]
catchret from %7 to label %rundefers.loophead4
rundefers.end1: ; preds = %rundefers.loophead4
br label %recover
}
declare i32 @__gxx_wasm_personality_v0(...)
declare void @runtime.setupDeferFrameWasmEH(ptr dereferenceable_or_null(16), ptr) #2
declare void @runtime.destroyDeferFrameWasmEH(ptr dereferenceable_or_null(16), ptr) #2
define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #2 {
entry:
call void @runtime.printint32(i32 3, ptr undef)
ret void
}
declare void @runtime.printint32(i32, ptr) #2
define hidden void @main.deferMultiple(ptr %context) unnamed_addr #2 personality ptr @__gxx_wasm_personality_v0 {
entry:
%defer.alloca2 = alloca { i32, ptr }, align 8
%defer.alloca = alloca { i32, ptr }, align 8
%deferPtr = alloca ptr, align 4
store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrameWasmEH, align 8
call void @runtime.setupDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
%stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr nonnull %defer.alloca, ptr nonnull %stackalloc, ptr undef)
store i32 0, ptr %defer.alloca, align 4
%defer.alloca.repack16 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
store ptr null, ptr %defer.alloca.repack16, align 4
store ptr %defer.alloca, ptr %deferPtr, align 4
call void @runtime.trackPointer(ptr nonnull %defer.alloca2, ptr nonnull %stackalloc, ptr undef)
store i32 1, ptr %defer.alloca2, align 4
%defer.alloca2.repack17 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca2, i32 0, i32 1
store ptr %defer.alloca, ptr %defer.alloca2.repack17, align 4
store ptr %defer.alloca2, ptr %deferPtr, align 4
invoke void @main.external(ptr undef)
to label %invoke.cont unwind label %catch.dispatch
invoke.cont: ; preds = %entry
br label %rundefers.block
rundefers.after: ; preds = %rundefers.end
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
ret void
rundefers.block: ; preds = %invoke.cont
br label %rundefers.loophead
rundefers.loophead: ; preds = %rundefers.catch.start, %rundefers.callback1, %rundefers.callback0, %rundefers.block
%0 = load ptr, ptr %deferPtr, align 4
%stackIsNil = icmp eq ptr %0, null
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds %runtime._defer, ptr %0, 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 %0, align 4
switch i32 %callback, label %rundefers.default [
i32 0, label %rundefers.callback0
i32 1, label %rundefers.callback1
]
rundefers.callback0: ; preds = %rundefers.loop
invoke void @"main.deferMultiple$1"(ptr undef)
to label %rundefers.loophead unwind label %rundefers.catch.dispatch
rundefers.callback1: ; preds = %rundefers.loop
invoke void @"main.deferMultiple$2"(ptr undef)
to label %rundefers.loophead unwind label %rundefers.catch.dispatch
rundefers.default: ; preds = %rundefers.loop
unreachable
rundefers.catch.dispatch: ; preds = %rundefers.callback1, %rundefers.callback0
%1 = catchswitch within none [label %rundefers.catch.start] unwind to caller
rundefers.catch.start: ; preds = %rundefers.catch.dispatch
%2 = catchpad within %1 [ptr null]
catchret from %2 to label %rundefers.loophead
rundefers.end: ; preds = %rundefers.loophead
br label %rundefers.after
recover: ; preds = %rundefers.end3
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
ret void
catch.dispatch: ; preds = %entry
%3 = catchswitch within none [label %catch.start] unwind to caller
catch.start: ; preds = %catch.dispatch
%4 = catchpad within %3 [ptr null]
catchret from %4 to label %rundefers
rundefers: ; preds = %catch.start
br label %rundefers.loophead6
rundefers.loophead6: ; preds = %rundefers.catch.start8, %rundefers.callback115, %rundefers.callback014, %rundefers
%5 = load ptr, ptr %deferPtr, align 4
%stackIsNil9 = icmp eq ptr %5, null
br i1 %stackIsNil9, label %rundefers.end3, label %rundefers.loop5
rundefers.loop5: ; preds = %rundefers.loophead6
%stack.next.gep10 = getelementptr inbounds %runtime._defer, ptr %5, i32 0, i32 1
%stack.next11 = load ptr, ptr %stack.next.gep10, align 4
store ptr %stack.next11, ptr %deferPtr, align 4
%callback13 = load i32, ptr %5, align 4
switch i32 %callback13, label %rundefers.default4 [
i32 0, label %rundefers.callback014
i32 1, label %rundefers.callback115
]
rundefers.callback014: ; preds = %rundefers.loop5
invoke void @"main.deferMultiple$1"(ptr undef)
to label %rundefers.loophead6 unwind label %rundefers.catch.dispatch7
rundefers.callback115: ; preds = %rundefers.loop5
invoke void @"main.deferMultiple$2"(ptr undef)
to label %rundefers.loophead6 unwind label %rundefers.catch.dispatch7
rundefers.default4: ; preds = %rundefers.loop5
unreachable
rundefers.catch.dispatch7: ; preds = %rundefers.callback115, %rundefers.callback014
%6 = catchswitch within none [label %rundefers.catch.start8] unwind to caller
rundefers.catch.start8: ; preds = %rundefers.catch.dispatch7
%7 = catchpad within %6 [ptr null]
catchret from %7 to label %rundefers.loophead6
rundefers.end3: ; preds = %rundefers.loophead6
br label %recover
}
define internal void @"main.deferMultiple$1"(ptr %context) unnamed_addr #2 {
entry:
call void @runtime.printint32(i32 3, ptr undef)
ret void
}
define internal void @"main.deferMultiple$2"(ptr %context) unnamed_addr #2 {
entry:
call void @runtime.printint32(i32 5, ptr undef)
ret void
}
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
+12 -12
View File
@@ -6,16 +6,17 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.f32tou32(float %v, ptr %context) unnamed_addr #2 { define hidden i32 @main.f32tou32(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%positive = fcmp oge float %v, 0.000000e+00 %positive = fcmp oge float %v, 0.000000e+00
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000 %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
@@ -27,25 +28,25 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.maxu32f(ptr %context) unnamed_addr #2 { define hidden float @main.maxu32f(ptr %context) unnamed_addr #1 {
entry: entry:
ret float 0x41F0000000000000 ret float 0x41F0000000000000
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.maxu32tof32(ptr %context) unnamed_addr #2 { define hidden i32 @main.maxu32tof32(ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 -1 ret i32 -1
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { i32, i32, i32, i32 } @main.inftoi32(ptr %context) unnamed_addr #2 { define hidden { i32, i32, i32, i32 } @main.inftoi32(ptr %context) unnamed_addr #1 {
entry: entry:
ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 } ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.u32tof32tou32(i32 %v, ptr %context) unnamed_addr #2 { define hidden i32 @main.u32tof32tou32(i32 %v, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = uitofp i32 %v to float %0 = uitofp i32 %v to float
%withinmax = fcmp ole float %0, 0x41EFFFFFC0000000 %withinmax = fcmp ole float %0, 0x41EFFFFFC0000000
@@ -55,7 +56,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.f32tou32tof32(float %v, ptr %context) unnamed_addr #2 { define hidden float @main.f32tou32tof32(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%positive = fcmp oge float %v, 0.000000e+00 %positive = fcmp oge float %v, 0.000000e+00
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000 %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
@@ -68,7 +69,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.f32tou8(float %v, ptr %context) unnamed_addr #2 { define hidden i8 @main.f32tou8(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%positive = fcmp oge float %v, 0.000000e+00 %positive = fcmp oge float %v, 0.000000e+00
%withinmax = fcmp ole float %v, 2.550000e+02 %withinmax = fcmp ole float %v, 2.550000e+02
@@ -80,7 +81,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.f32toi8(float %v, ptr %context) unnamed_addr #2 { define hidden i8 @main.f32toi8(float %v, ptr %context) unnamed_addr #1 {
entry: entry:
%abovemin = fcmp oge float %v, -1.280000e+02 %abovemin = fcmp oge float %v, -1.280000e+02
%belowmax = fcmp ole float %v, 1.270000e+02 %belowmax = fcmp ole float %v, 1.270000e+02
@@ -93,6 +94,5 @@ entry:
ret i8 %0 ret i8 %0
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
+9 -8
View File
@@ -6,16 +6,17 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.foo(ptr %callback.context, ptr %callback.funcptr, ptr %context) unnamed_addr #2 { define hidden void @main.foo(ptr %callback.context, ptr %callback.funcptr, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp eq ptr %callback.funcptr, null %0 = icmp eq ptr %callback.funcptr, null
br i1 %0, label %fpcall.throw, label %fpcall.next br i1 %0, label %fpcall.throw, label %fpcall.next
@@ -29,22 +30,22 @@ fpcall.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.nilPanic(ptr) #1 declare void @runtime.nilPanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.bar(ptr %context) unnamed_addr #2 { define hidden void @main.bar(ptr %context) unnamed_addr #1 {
entry: entry:
call void @main.foo(ptr undef, ptr nonnull @main.someFunc, ptr undef) call void @main.foo(ptr undef, ptr nonnull @main.someFunc, ptr undef)
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.someFunc(i32 %arg0, ptr %context) unnamed_addr #2 { define hidden void @main.someFunc(i32 %arg0, ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+45 -45
View File
@@ -27,93 +27,94 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.newScalar(ptr %context) unnamed_addr #2 { define hidden void @main.newScalar(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%new = call align 1 dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new = call align 1 dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
store ptr %new, ptr @main.scalar1, align 4 store ptr %new, ptr @main.scalar1, align 4
%new1 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new1 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef)
store ptr %new1, ptr @main.scalar2, align 4 store ptr %new1, ptr @main.scalar2, align 4
%new2 = call align 8 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new2 = call align 8 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef)
store ptr %new2, ptr @main.scalar3, align 4 store ptr %new2, ptr @main.scalar3, align 4
%new3 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new3 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef)
store ptr %new3, ptr @main.scalar4, align 4 store ptr %new3, ptr @main.scalar4, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.newArray(ptr %context) unnamed_addr #2 { define hidden void @main.newArray(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%new = call align 1 dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new = call align 1 dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
store ptr %new, ptr @main.array1, align 4 store ptr %new, ptr @main.array1, align 4
%new1 = call align 1 dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new1 = call align 1 dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef)
store ptr %new1, ptr @main.array2, align 4 store ptr %new1, ptr @main.array2, align 4
%new2 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3 %new2 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef)
store ptr %new2, ptr @main.array3, align 4 store ptr %new2, ptr @main.array3, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.newStruct(ptr %context) unnamed_addr #2 { define hidden void @main.newStruct(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%new = call align 1 ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new = call align 1 ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
store ptr %new, ptr @main.struct1, align 4 store ptr %new, ptr @main.struct1, align 4
%new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef)
store ptr %new1, ptr @main.struct2, align 4 store ptr %new1, ptr @main.struct2, align 4
%new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #3 %new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef)
store ptr %new2, ptr @main.struct3, align 4 store ptr %new2, ptr @main.struct3, align 4
%new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #3 %new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef)
store ptr %new3, ptr @main.struct4, align 4 store ptr %new3, ptr @main.struct4, align 4
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #2 { define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%new = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #3 %new = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
ret ptr %new ret ptr %new
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.makeSlice(ptr %context) unnamed_addr #2 { define hidden void @main.makeSlice(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef)
store ptr %makeslice, ptr @main.slice1, align 4 store ptr %makeslice, ptr @main.slice1, align 4
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 1), align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 4
%makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3 %makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr nonnull %stackalloc, ptr undef)
store ptr %makeslice1, ptr @main.slice2, align 4 store ptr %makeslice1, ptr @main.slice2, align 4
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 1), align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 4
%makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3 %makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr nonnull %stackalloc, ptr undef)
store ptr %makeslice3, ptr @main.slice3, align 4 store ptr %makeslice3, ptr @main.slice3, align 4
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 1), align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 2), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 2), align 4
@@ -121,21 +122,20 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #2 { define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3 %0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #2
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef)
store double %v.r, ptr %0, align 8 store double %v.r, ptr %0, align 8
%.repack1 = getelementptr inbounds { double, double }, ptr %0, i32 0, i32 1 %.repack1 = getelementptr inbounds { double, double }, ptr %0, i32 0, i32 1
store double %v.i, ptr %.repack1, align 8 store double %v.i, ptr %.repack1, align 8
%1 = insertvalue %runtime._interface { ptr @"reflect/types.type:basic:complex128", ptr undef }, ptr %0, 1 %1 = insertvalue %runtime._interface { ptr @"reflect/types.type:basic:complex128", ptr undef }, ptr %0, 1
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:complex128", ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:complex128", ptr nonnull %stackalloc, ptr undef)
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef)
ret %runtime._interface %1 ret %runtime._interface %1
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { nounwind }
attributes #3 = { nounwind }
+12 -11
View File
@@ -8,24 +8,25 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.unsafeSliceData(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 { define hidden ptr @main.unsafeSliceData(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef)
ret ptr %s.data ret ptr %s.data
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.unsafeString(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.unsafeString(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = icmp slt i16 %len, 0 %0 = icmp slt i16 %len, 0
@@ -39,7 +40,7 @@ unsafe.String.next: ; preds = %entry
%5 = zext i16 %len to i32 %5 = zext i16 %len to i32
%6 = insertvalue %runtime._string undef, ptr %ptr, 0 %6 = insertvalue %runtime._string undef, ptr %ptr, 0
%7 = insertvalue %runtime._string %6, i32 %5, 1 %7 = insertvalue %runtime._string %6, i32 %5, 1
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
ret %runtime._string %7 ret %runtime._string %7
unsafe.String.throw: ; preds = %entry unsafe.String.throw: ; preds = %entry
@@ -47,17 +48,17 @@ unsafe.String.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.unsafeSlicePanic(ptr) #1 declare void @runtime.unsafeSlicePanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.unsafeStringData(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #2 { define hidden ptr @main.unsafeStringData(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef)
ret ptr %s.data ret ptr %s.data
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+25 -24
View File
@@ -8,29 +8,30 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.min1(i32 %a, ptr %context) unnamed_addr #2 { define hidden i32 @main.min1(i32 %a, ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 %a ret i32 %a
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.min2(i32 %a, i32 %b, ptr %context) unnamed_addr #2 { define hidden i32 @main.min2(i32 %a, i32 %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b) %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
ret i32 %0 ret i32 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.min3(i32 %a, i32 %b, i32 %c, ptr %context) unnamed_addr #2 { define hidden i32 @main.min3(i32 %a, i32 %b, i32 %c, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b) %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
%1 = call i32 @llvm.smin.i32(i32 %0, i32 %c) %1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)
@@ -38,7 +39,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.min4(i32 %a, i32 %b, i32 %c, i32 %d, ptr %context) unnamed_addr #2 { define hidden i32 @main.min4(i32 %a, i32 %b, i32 %c, i32 %d, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b) %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
%1 = call i32 @llvm.smin.i32(i32 %0, i32 %c) %1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)
@@ -47,21 +48,21 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.minUint8(i8 %a, i8 %b, ptr %context) unnamed_addr #2 { define hidden i8 @main.minUint8(i8 %a, i8 %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8 @llvm.umin.i8(i8 %a, i8 %b) %0 = call i8 @llvm.umin.i8(i8 %a, i8 %b)
ret i8 %0 ret i8 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.minUnsigned(i32 %a, i32 %b, ptr %context) unnamed_addr #2 { define hidden i32 @main.minUnsigned(i32 %a, i32 %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i32 @llvm.umin.i32(i32 %a, i32 %b) %0 = call i32 @llvm.umin.i32(i32 %a, i32 %b)
ret i32 %0 ret i32 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.minFloat32(float %a, float %b, ptr %context) unnamed_addr #2 { define hidden float @main.minFloat32(float %a, float %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp olt float %a, %b %0 = fcmp olt float %a, %b
%1 = select i1 %0, float %a, float %b %1 = select i1 %0, float %a, float %b
@@ -69,7 +70,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden double @main.minFloat64(double %a, double %b, ptr %context) unnamed_addr #2 { define hidden double @main.minFloat64(double %a, double %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp olt double %a, %b %0 = fcmp olt double %a, %b
%1 = select i1 %0, double %a, double %b %1 = select i1 %0, double %a, double %b
@@ -77,7 +78,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.minString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.minString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0 %0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0
%1 = insertvalue %runtime._string %0, i32 %a.len, 1 %1 = insertvalue %runtime._string %0, i32 %a.len, 1
@@ -87,28 +88,28 @@ entry:
%4 = call i1 @runtime.stringLess(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr undef) #5 %4 = call i1 @runtime.stringLess(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr undef) #5
%5 = select i1 %4, %runtime._string %1, %runtime._string %3 %5 = select i1 %4, %runtime._string %1, %runtime._string %3
%6 = extractvalue %runtime._string %5, 0 %6 = extractvalue %runtime._string %5, 0
call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5 call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef)
ret %runtime._string %5 ret %runtime._string %5
} }
declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #1 declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.maxInt(i32 %a, i32 %b, ptr %context) unnamed_addr #2 { define hidden i32 @main.maxInt(i32 %a, i32 %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i32 @llvm.smax.i32(i32 %a, i32 %b) %0 = call i32 @llvm.smax.i32(i32 %a, i32 %b)
ret i32 %0 ret i32 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.maxUint(i32 %a, i32 %b, ptr %context) unnamed_addr #2 { define hidden i32 @main.maxUint(i32 %a, i32 %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i32 @llvm.umax.i32(i32 %a, i32 %b) %0 = call i32 @llvm.umax.i32(i32 %a, i32 %b)
ret i32 %0 ret i32 %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden float @main.maxFloat32(float %a, float %b, ptr %context) unnamed_addr #2 { define hidden float @main.maxFloat32(float %a, float %b, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = fcmp ogt float %a, %b %0 = fcmp ogt float %a, %b
%1 = select i1 %0, float %a, float %b %1 = select i1 %0, float %a, float %b
@@ -116,7 +117,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.maxString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.maxString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0 %0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0
%1 = insertvalue %runtime._string %0, i32 %a.len, 1 %1 = insertvalue %runtime._string %0, i32 %a.len, 1
@@ -126,12 +127,12 @@ entry:
%4 = call i1 @runtime.stringLess(ptr %b.data, i32 %b.len, ptr %a.data, i32 %a.len, ptr undef) #5 %4 = call i1 @runtime.stringLess(ptr %b.data, i32 %b.len, ptr %a.data, i32 %a.len, ptr undef) #5
%5 = select i1 %4, %runtime._string %1, %runtime._string %3 %5 = select i1 %4, %runtime._string %1, %runtime._string %3
%6 = extractvalue %runtime._string %5, 0 %6 = extractvalue %runtime._string %5, 0
call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5 call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef)
ret %runtime._string %5 ret %runtime._string %5
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.clearSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 { define hidden void @main.clearSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = shl i32 %s.len, 2 %0 = shl i32 %s.len, 2
call void @llvm.memset.p0.i32(ptr align 4 %s.data, i8 0, i32 %0, i1 false) call void @llvm.memset.p0.i32(ptr align 4 %s.data, i8 0, i32 %0, i1 false)
@@ -142,19 +143,19 @@ entry:
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #3 declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #3
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 { define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.clearMap(ptr dereferenceable_or_null(40) %m, ptr %context) unnamed_addr #2 { define hidden void @main.clearMap(ptr dereferenceable_or_null(40) %m, ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.hashmapClear(ptr %m, ptr undef) #5 call void @runtime.hashmapClear(ptr %m, ptr undef) #5
ret void ret void
} }
declare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #1 declare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #2
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.smin.i32(i32, i32) #4 declare i32 @llvm.smin.i32(i32, i32) #4
@@ -171,9 +172,9 @@ declare i32 @llvm.smax.i32(i32, i32) #4
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.umax.i32(i32, i32) #4 declare i32 @llvm.umax.i32(i32, i32) #4
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) } attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #5 = { nounwind } attributes #5 = { nounwind }
+33 -32
View File
@@ -10,24 +10,25 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #2 { define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
ret void ret void
} }
declare void @main.regularFunction(i32, ptr) #1 declare void @main.regularFunction(i32, ptr) #2
declare void @runtime.deadlock(ptr) #1 declare void @runtime.deadlock(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 { define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
@@ -38,17 +39,17 @@ entry:
unreachable unreachable
} }
declare void @"internal/task.start"(i32, ptr, i32, ptr) #1 declare void @"internal/task.start"(i32, ptr, i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #2 { define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #2 { define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
@@ -63,16 +64,16 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #2 { define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9 %n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef)
store i32 3, ptr %n, align 4 store i32 3, ptr %n, align 4
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef)
call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef)
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef)
store i32 5, ptr %0, align 4 store i32 5, ptr %0, align 4
%1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1 %1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
store ptr %n, ptr %1, align 4 store ptr %n, ptr %1, align 4
@@ -83,7 +84,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #2 { define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
entry: entry:
store i32 7, ptr %context, align 4 store i32 7, ptr %context, align 4
ret void ret void
@@ -100,14 +101,14 @@ entry:
unreachable unreachable
} }
declare void @runtime.printint32(i32, ptr) #1 declare void @runtime.printint32(i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 { define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef)
store i32 5, ptr %0, align 4 store i32 5, ptr %0, align 4
%1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1 %1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
store ptr %fn.context, ptr %1, align 4 store ptr %fn.context, ptr %1, align 4
@@ -131,35 +132,35 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #2 { define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
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 #2 { 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: entry:
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9 %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9
ret void ret void
} }
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1 declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 { define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
call void @runtime.chanClose(ptr %ch, ptr undef) #9 call void @runtime.chanClose(ptr %ch, ptr undef) #9
ret void ret void
} }
declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #1 declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 { define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef)
store ptr %itf.value, ptr %0, align 4 store ptr %itf.value, ptr %0, align 4
%1 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1 %1 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1
store ptr @"main$string", ptr %1, align 4 store ptr @"main$string", ptr %1, align 4
@@ -188,13 +189,13 @@ entry:
unreachable unreachable
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.regularFunction" } attributes #3 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.regularFunction" }
attributes #4 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" } attributes #4 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
attributes #5 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" } attributes #5 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
attributes #6 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper" } attributes #6 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper" }
attributes #7 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" } attributes #7 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
attributes #8 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" } attributes #8 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
attributes #9 = { nounwind } attributes #9 = { nounwind }
+28 -27
View File
@@ -20,52 +20,53 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.simpleType(ptr %context) unnamed_addr #2 { define hidden %runtime._interface @main.simpleType(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:int", ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:int", ptr nonnull %stackalloc, ptr undef)
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
ret %runtime._interface { ptr @"reflect/types.type:basic:int", ptr null } ret %runtime._interface { ptr @"reflect/types.type:basic:int", ptr null }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.pointerType(ptr %context) unnamed_addr #2 { define hidden %runtime._interface @main.pointerType(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:basic:int", ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:basic:int", ptr nonnull %stackalloc, ptr undef)
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
ret %runtime._interface { ptr @"reflect/types.type:pointer:basic:int", ptr null } ret %runtime._interface { ptr @"reflect/types.type:pointer:basic:int", ptr null }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.interfaceType(ptr %context) unnamed_addr #2 { define hidden %runtime._interface @main.interfaceType(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:named:error", ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:named:error", ptr nonnull %stackalloc, ptr undef)
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
ret %runtime._interface { ptr @"reflect/types.type:pointer:named:error", ptr null } ret %runtime._interface { ptr @"reflect/types.type:pointer:named:error", ptr null }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._interface @main.anonymousInterfaceType(ptr %context) unnamed_addr #2 { define hidden %runtime._interface @main.anonymousInterfaceType(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr nonnull %stackalloc, ptr undef)
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
ret %runtime._interface { ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr null } ret %runtime._interface { ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr null }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.isInt(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 { define hidden i1 @main.isInt(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%typecode = call i1 @runtime.typeAssert(ptr %itf.typecode, ptr nonnull @"reflect/types.typeid:basic:int", ptr undef) #7 %typecode = call i1 @runtime.typeAssert(ptr %itf.typecode, ptr nonnull @"reflect/types.typeid:basic:int", ptr undef) #7
br i1 %typecode, label %typeassert.ok, label %typeassert.next br i1 %typecode, label %typeassert.ok, label %typeassert.next
@@ -77,10 +78,10 @@ typeassert.ok: ; preds = %entry
br label %typeassert.next br label %typeassert.next
} }
declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #1 declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.isError(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 { define hidden i1 @main.isError(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(ptr %itf.typecode) #7 %0 = call i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(ptr %itf.typecode) #7
br i1 %0, label %typeassert.ok, label %typeassert.next br i1 %0, label %typeassert.ok, label %typeassert.next
@@ -95,7 +96,7 @@ typeassert.ok: ; preds = %entry
declare i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(ptr) #3 declare i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(ptr) #3
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.isStringer(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 { define hidden i1 @main.isStringer(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(ptr %itf.typecode) #7 %0 = call i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(ptr %itf.typecode) #7
br i1 %0, label %typeassert.ok, label %typeassert.next br i1 %0, label %typeassert.ok, label %typeassert.next
@@ -110,7 +111,7 @@ typeassert.ok: ; preds = %entry
declare i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(ptr) #4 declare i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(ptr) #4
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.callFooMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 { define hidden i8 @main.callFooMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr %itf.value, i32 3, ptr %itf.typecode, ptr undef) #7 %0 = call i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr %itf.value, i32 3, ptr %itf.typecode, ptr undef) #7
ret i8 %0 ret i8 %0
@@ -119,22 +120,22 @@ entry:
declare i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr, i32, ptr, ptr) #5 declare i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr, i32, ptr, ptr) #5
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.callErrorMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.callErrorMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = call %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr %itf.value, ptr %itf.typecode, ptr undef) #7 %0 = call %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr %itf.value, ptr %itf.typecode, ptr undef) #7
%1 = extractvalue %runtime._string %0, 0 %1 = extractvalue %runtime._string %0, 0
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #7 call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef)
ret %runtime._string %0 ret %runtime._string %0
} }
declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr, ptr, ptr) #6 declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr, ptr, ptr) #6
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-methods"="reflect/methods.Error() string" } attributes #3 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-methods"="reflect/methods.Error() string" }
attributes #4 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-methods"="reflect/methods.String() string" } attributes #4 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-methods"="reflect/methods.String() string" }
attributes #5 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" } attributes #5 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" }
attributes #6 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" } attributes #6 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" }
attributes #7 = { nounwind } attributes #7 = { nounwind }
+11 -12
View File
@@ -6,45 +6,44 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden [0 x i32] @main.pointerDerefZero(ptr %x, ptr %context) unnamed_addr #2 { define hidden [0 x i32] @main.pointerDerefZero(ptr %x, ptr %context) unnamed_addr #1 {
entry: entry:
ret [0 x i32] zeroinitializer ret [0 x i32] zeroinitializer
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.pointerCastFromUnsafe(ptr %x, ptr %context) unnamed_addr #2 { define hidden ptr @main.pointerCastFromUnsafe(ptr %x, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef)
ret ptr %x ret ptr %x
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.pointerCastToUnsafe(ptr dereferenceable_or_null(4) %x, ptr %context) unnamed_addr #2 { define hidden ptr @main.pointerCastToUnsafe(ptr dereferenceable_or_null(4) %x, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef)
ret ptr %x ret ptr %x
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.pointerCastToUnsafeNoop(ptr dereferenceable_or_null(1) %x, ptr %context) unnamed_addr #2 { define hidden ptr @main.pointerCastToUnsafeNoop(ptr dereferenceable_or_null(1) %x, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef)
ret ptr %x ret ptr %x
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nounwind }
+16 -15
View File
@@ -14,27 +14,28 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define void @extern_func() #3 { define void @extern_func() #2 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @somepkg.someFunction1(ptr %context) unnamed_addr #2 { define hidden void @somepkg.someFunction1(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
declare void @somepkg.someFunction2(ptr) #1 declare void @somepkg.someFunction2(ptr) #3
; Function Attrs: inlinehint nounwind ; Function Attrs: inlinehint nounwind
define hidden void @main.inlineFunc(ptr %context) unnamed_addr #4 { define hidden void @main.inlineFunc(ptr %context) unnamed_addr #4 {
@@ -70,15 +71,15 @@ entry:
ret void ret void
} }
declare void @main.undefinedFunctionNotInSection(ptr) #1 declare void @main.undefinedFunctionNotInSection(ptr) #3
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" }
attributes #3 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" } attributes #3 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #4 = { inlinehint nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #4 = { inlinehint nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #5 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #5 = { noinline nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #6 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" } attributes #6 = { noinline nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" }
attributes #7 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="modulename" "wasm-import-name"="import1" } attributes #7 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="modulename" "wasm-import-name"="import1" }
attributes #8 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="foobar" "wasm-import-name"="imported" } attributes #8 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="foobar" "wasm-import-name"="imported" }
attributes #9 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exported" } attributes #9 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exported" }
+43 -42
View File
@@ -6,28 +6,29 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 { define hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 %ints.len ret i32 %ints.len
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 { define hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 %ints.cap ret i32 %ints.cap
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, ptr %context) unnamed_addr #2 { define hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, ptr %context) unnamed_addr #1 {
entry: entry:
%.not = icmp ult i32 %index, %ints.len %.not = icmp ult i32 %index, %ints.len
br i1 %.not, label %lookup.next, label %lookup.throw br i1 %.not, label %lookup.next, label %lookup.throw
@@ -42,14 +43,14 @@ lookup.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.lookupPanic(ptr) #1 declare void @runtime.lookupPanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef)
store i32 1, ptr %varargs, align 4 store i32 1, ptr %varargs, align 4
%0 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 1 %0 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 1
store i32 2, ptr %0, align 4 store i32 2, ptr %0, align 4
@@ -62,14 +63,14 @@ entry:
%2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0 %2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
%3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1 %3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1
%4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2 %4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %4 ret { ptr, i32, i32 } %4
} }
declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #1 declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
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 #2 { 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: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%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) #3 %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) #3
@@ -79,21 +80,21 @@ entry:
%0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0 %0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1 %1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2 %2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %2 ret { ptr, i32, i32 } %2
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
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 #2 { 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: entry:
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 4, ptr undef) #3 %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 4, ptr undef) #3
ret i32 %copy.n ret i32 %copy.n
} }
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1 declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%slice.maxcap = icmp slt i32 %len, 0 %slice.maxcap = icmp slt i32 %len, 0
@@ -104,7 +105,7 @@ slice.next: ; preds = %entry
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %2 ret { ptr, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
@@ -112,10 +113,10 @@ slice.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.slicePanic(ptr) #1 declare void @runtime.slicePanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.makeInt16Slice(i32 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.makeInt16Slice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%slice.maxcap = icmp slt i32 %len, 0 %slice.maxcap = icmp slt i32 %len, 0
@@ -127,7 +128,7 @@ slice.next: ; preds = %entry
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %2 ret { ptr, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
@@ -136,7 +137,7 @@ slice.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.makeArraySlice(i32 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.makeArraySlice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%slice.maxcap = icmp ugt i32 %len, 1431655765 %slice.maxcap = icmp ugt i32 %len, 1431655765
@@ -148,7 +149,7 @@ slice.next: ; preds = %entry
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %2 ret { ptr, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
@@ -157,7 +158,7 @@ slice.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.makeInt32Slice(i32 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.makeInt32Slice(i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%slice.maxcap = icmp ugt i32 %len, 1073741823 %slice.maxcap = icmp ugt i32 %len, 1073741823
@@ -169,7 +170,7 @@ slice.next: ; preds = %entry
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %2 ret { ptr, i32, i32 } %2
slice.throw: ; preds = %entry slice.throw: ; preds = %entry
@@ -178,26 +179,26 @@ slice.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #2 { define hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = getelementptr i8, ptr %p, i32 %len %0 = getelementptr i8, ptr %p, i32 %len
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef)
ret ptr %0 ret ptr %0
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.Add64(ptr %p, i64 %len, ptr %context) unnamed_addr #2 { define hidden ptr @main.Add64(ptr %p, i64 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = trunc i64 %len to i32 %0 = trunc i64 %len to i32
%1 = getelementptr i8, ptr %p, i32 %0 %1 = getelementptr i8, ptr %p, i32 %0
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef)
ret ptr %1 ret ptr %1
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 { define hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = icmp ult i32 %s.len, 4 %0 = icmp ult i32 %s.len, 4
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
@@ -210,14 +211,14 @@ slicetoarray.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.sliceToArrayPointerPanic(ptr) #1 declare void @runtime.sliceToArrayPointerPanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #2 { define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef)
br i1 false, label %slicetoarray.throw, label %slicetoarray.next br i1 false, label %slicetoarray.throw, label %slicetoarray.next
slicetoarray.next: ; preds = %entry slicetoarray.next: ; preds = %entry
@@ -228,7 +229,7 @@ slicetoarray.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.SliceInt(ptr dereferenceable_or_null(4) %ptr, i32 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.SliceInt(ptr dereferenceable_or_null(4) %ptr, i32 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = icmp ugt i32 %len, 1073741823 %0 = icmp ugt i32 %len, 1073741823
@@ -242,7 +243,7 @@ unsafe.Slice.next: ; preds = %entry
%5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0 %5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1 %6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1
%7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2 %7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %7 ret { ptr, i32, i32 } %7
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
@@ -250,10 +251,10 @@ unsafe.Slice.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.unsafeSlicePanic(ptr) #1 declare void @runtime.unsafeSlicePanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.SliceUint16(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.SliceUint16(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = icmp eq ptr %ptr, null %0 = icmp eq ptr %ptr, null
@@ -266,7 +267,7 @@ unsafe.Slice.next: ; preds = %entry
%4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0 %4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1 %5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1
%6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2 %6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %6 ret { ptr, i32, i32 } %6
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
@@ -275,7 +276,7 @@ unsafe.Slice.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.SliceUint64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.SliceUint64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = icmp ugt i64 %len, 1073741823 %0 = icmp ugt i64 %len, 1073741823
@@ -290,7 +291,7 @@ unsafe.Slice.next: ; preds = %entry
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0 %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1 %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2 %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %8 ret { ptr, i32, i32 } %8
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
@@ -299,7 +300,7 @@ unsafe.Slice.throw: ; preds = %entry
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden { ptr, i32, i32 } @main.SliceInt64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #2 { define hidden { ptr, i32, i32 } @main.SliceInt64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #1 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%0 = icmp ugt i64 %len, 1073741823 %0 = icmp ugt i64 %len, 1073741823
@@ -314,7 +315,7 @@ unsafe.Slice.next: ; preds = %entry
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0 %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1 %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2 %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
ret { ptr, i32, i32 } %8 ret { ptr, i32, i32 } %8
unsafe.Slice.throw: ; preds = %entry unsafe.Slice.throw: ; preds = %entry
@@ -322,7 +323,7 @@ unsafe.Slice.throw: ; preds = %entry
unreachable unreachable
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+16 -15
View File
@@ -10,34 +10,35 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.someString(ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.someString(ptr %context) unnamed_addr #1 {
entry: entry:
ret %runtime._string { ptr @"main$string", i32 3 } ret %runtime._string { ptr @"main$string", i32 3 }
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.zeroLengthString(ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.zeroLengthString(ptr %context) unnamed_addr #1 {
entry: entry:
ret %runtime._string zeroinitializer ret %runtime._string zeroinitializer
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.stringLen(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #2 { define hidden i32 @main.stringLen(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #1 {
entry: entry:
ret i32 %s.len ret i32 %s.len
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.stringIndex(ptr %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #2 { define hidden i8 @main.stringIndex(ptr %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #1 {
entry: entry:
%.not = icmp ult i32 %index, %s.len %.not = icmp ult i32 %index, %s.len
br i1 %.not, label %lookup.next, label %lookup.throw br i1 %.not, label %lookup.next, label %lookup.throw
@@ -52,19 +53,19 @@ lookup.throw: ; preds = %entry
unreachable unreachable
} }
declare void @runtime.lookupPanic(ptr) #1 declare void @runtime.lookupPanic(ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 { define hidden i1 @main.stringCompareEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3 %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3
ret i1 %0 ret i1 %0
} }
declare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr) #1 declare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareUnequal(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 { define hidden i1 @main.stringCompareUnequal(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3 %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3
%1 = xor i1 %0, true %1 = xor i1 %0, true
@@ -72,16 +73,16 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareLarger(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 { define hidden i1 @main.stringCompareLarger(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len, ptr undef) #3 %0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len, ptr undef) #3
ret i1 %0 ret i1 %0
} }
declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #1 declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.stringLookup(ptr %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #2 { define hidden i8 @main.stringLookup(ptr %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #1 {
entry: entry:
%0 = zext i8 %x to i32 %0 = zext i8 %x to i32
%.not = icmp ult i32 %0, %s.len %.not = icmp ult i32 %0, %s.len
@@ -97,7 +98,7 @@ lookup.throw: ; preds = %entry
unreachable unreachable
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+17 -16
View File
@@ -8,16 +8,17 @@ target triple = "wasm32-unknown-wasi"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1 declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.init(ptr %context) unnamed_addr #2 { define hidden void @main.init(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
; Function Attrs: noinline nounwind ; Function Attrs: noinline nounwind
define hidden i32 @main.testZeroGet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #3 { define hidden i32 @main.testZeroGet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 {
entry: entry:
%hashmap.key = alloca %main.hasPadding, align 8 %hashmap.key = alloca %main.hasPadding, align 8
%hashmap.value = alloca i32, align 4 %hashmap.value = alloca i32, align 4
@@ -39,17 +40,17 @@ entry:
} }
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #4 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3
declare void @runtime.memzero(ptr, i32, ptr) #1 declare void @runtime.memzero(ptr, i32, ptr) #4
declare i1 @runtime.hashmapBinaryGet(ptr dereferenceable_or_null(40), ptr, ptr, i32, ptr) #1 declare i1 @runtime.hashmapBinaryGet(ptr dereferenceable_or_null(40), ptr, ptr, i32, ptr) #4
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #4 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3
; Function Attrs: noinline nounwind ; Function Attrs: noinline nounwind
define hidden void @main.testZeroSet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #3 { define hidden void @main.testZeroSet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 {
entry: entry:
%hashmap.key = alloca %main.hasPadding, align 8 %hashmap.key = alloca %main.hasPadding, align 8
%hashmap.value = alloca i32, align 4 %hashmap.value = alloca i32, align 4
@@ -70,10 +71,10 @@ entry:
ret void ret void
} }
declare void @runtime.hashmapBinarySet(ptr dereferenceable_or_null(40), ptr, ptr, ptr) #1 declare void @runtime.hashmapBinarySet(ptr dereferenceable_or_null(40), ptr, ptr, ptr) #4
; Function Attrs: noinline nounwind ; Function Attrs: noinline nounwind
define hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #3 { define hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #2 {
entry: entry:
%hashmap.key = alloca [2 x %main.hasPadding], align 8 %hashmap.key = alloca [2 x %main.hasPadding], align 8
%hashmap.value = alloca i32, align 4 %hashmap.value = alloca i32, align 4
@@ -100,7 +101,7 @@ entry:
} }
; Function Attrs: noinline nounwind ; Function Attrs: noinline nounwind
define hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #3 { define hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #2 {
entry: entry:
%hashmap.key = alloca [2 x %main.hasPadding], align 8 %hashmap.key = alloca [2 x %main.hasPadding], align 8
%hashmap.value = alloca i32, align 4 %hashmap.value = alloca i32, align 4
@@ -127,14 +128,14 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.main(ptr %context) unnamed_addr #2 { define hidden void @main.main(ptr %context) unnamed_addr #1 {
entry: entry:
ret void ret void
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #2 = { noinline nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #3 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" } attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #4 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } attributes #4 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
attributes #5 = { nounwind } attributes #5 = { nounwind }
+1 -1
View File
@@ -19,7 +19,7 @@ require (
golang.org/x/sys v0.21.0 golang.org/x/sys v0.21.0
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504 golang.org/x/tools v0.22.1-0.20240621165957-db513b091504
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8 tinygo.org/x/go-llvm v0.0.0-20240804145059-aaff3eb751f0
) )
require ( require (
+2 -2
View File
@@ -77,5 +77,5 @@ 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.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8 h1:bLsZXRUBavt++CJlMN7sppNziqu3LyamESLhFJcpqFQ= tinygo.org/x/go-llvm v0.0.0-20240804145059-aaff3eb751f0 h1:aN9rSxvVWmipB13yVAFOmRj3LX4Kkfiq/fSl5EAilDA=
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= tinygo.org/x/go-llvm v0.0.0-20240804145059-aaff3eb751f0/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+10 -2
View File
@@ -286,10 +286,18 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
runTest("rand.go", options, t, nil, nil) runTest("rand.go", options, t, nil, nil)
}) })
} }
if !isWebAssembly { if !isWASI {
// The recover() builtin isn't supported yet on WebAssembly and Windows. // On WebAssembly, recover() needs the exception handling proposal which
// isn't (as of 2024) implemented in wasmtime so this test is skipped on
// WASI.
t.Run("recover.go", func(t *testing.T) { t.Run("recover.go", func(t *testing.T) {
t.Parallel() t.Parallel()
options := options
if isWebAssembly {
// Hack: Asyncify doesn't support exception handling
// instructions.
options.Scheduler = "none"
}
runTest("recover.go", options, t, nil, nil) runTest("recover.go", options, t, nil, nil)
}) })
} }
+98 -28
View File
@@ -15,11 +15,20 @@ func trap()
// purposes of TinyGo. It restores the stack pointer and jumps to the given pc. // purposes of TinyGo. It restores the stack pointer and jumps to the given pc.
// //
//export tinygo_longjmp //export tinygo_longjmp
func tinygo_longjmp(frame *deferFrame) func tinygo_longjmp(frame *deferFrameInlineAsm)
// Compiler intrinsic. // Compiler intrinsic.
// Returns whether recover is supported on the current architecture. // Returns whether recover is supported on the current architecture.
func supportsRecover() bool func supportsRecover() recoverType
type recoverType uint8
const (
// Note: these contants match recoverSupport in compiler/defer.go
recoverNone recoverType = iota
recoverInlineAsm
recoverWasmEH
)
const ( const (
panicStrategyPrint = 1 panicStrategyPrint = 1
@@ -31,33 +40,55 @@ const (
// using the -panic= compiler flag. // using the -panic= compiler flag.
func panicStrategy() uint8 func panicStrategy() uint8
// DeferFrame is a stack allocated object that stores information for the // LLVM compiler intrinsic: this inserts a wasm 'throw' instruction.
// current "defer frame", which is used in functions that use the `defer` //
//export llvm.wasm.throw
func wasm_throw(uint32, unsafe.Pointer)
// DeferFrameInlineAsm is a stack allocated object that stores information for
// the current "defer frame", which is used in functions that use the `defer`
// keyword. // keyword.
// The compiler knows about the JumpPC struct offset, so it should not be moved // The compiler knows about the JumpPC struct offset, so it should not be moved
// without also updating compiler/defer.go. // without also updating compiler/defer.go.
type deferFrame struct { type deferFrameInlineAsm struct {
JumpSP unsafe.Pointer // stack pointer to return to JumpSP unsafe.Pointer // stack pointer to return to
JumpPC unsafe.Pointer // pc to return to JumpPC unsafe.Pointer // pc to return to
ExtraRegs [deferExtraRegs]unsafe.Pointer // extra registers (depending on the architecture) ExtraRegs [deferExtraRegs]unsafe.Pointer // extra registers (depending on the architecture)
Previous *deferFrame // previous recover buffer pointer Previous *deferFrameInlineAsm // previous recover buffer pointer
Panicking bool // true iff this defer frame is panicking Panicking bool // true iff this defer frame is panicking
PanicValue interface{} // panic value, might be nil for panic(nil) for example PanicValue interface{} // panic value, might be nil for panic(nil) for example
} }
// DeferFrameWasmEH is like deferFrameInlineAsm but for WebAssembly exception
// handling.
type deferFrameWasmEH struct {
Previous *deferFrameWasmEH // previous recover buffer pointer
Panicking bool // true iff this defer frame is panicking
PanicValue interface{} // panic value, might be nil for panic(nil) for example
}
// Builtin function panic(msg), used as a compiler intrinsic. // Builtin function panic(msg), used as a compiler intrinsic.
func _panic(message interface{}) { func _panic(message interface{}) {
if panicStrategy() == panicStrategyTrap { if panicStrategy() == panicStrategyTrap {
trap() trap()
} }
if supportsRecover() { switch supportsRecover() {
frame := (*deferFrame)(task.Current().DeferFrame) case recoverInlineAsm:
frame := (*deferFrameInlineAsm)(task.Current().DeferFrame)
if frame != nil { if frame != nil {
frame.PanicValue = message frame.PanicValue = message
frame.Panicking = true frame.Panicking = true
tinygo_longjmp(frame) tinygo_longjmp(frame)
// unreachable // unreachable
} }
case recoverWasmEH:
frame := (*deferFrameWasmEH)(task.Current().DeferFrame)
if frame != nil {
frame.PanicValue = message
frame.Panicking = true
wasm_throw(0, nil)
// unreachable
}
} }
printstring("panic: ") printstring("panic: ")
printitf(message) printitf(message)
@@ -94,21 +125,43 @@ func runtimePanicAt(addr unsafe.Pointer, msg string) {
// //
//go:inline //go:inline
//go:nobounds //go:nobounds
func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) { func setupDeferFrameInlineAsm(frame *deferFrameInlineAsm, jumpSP unsafe.Pointer) {
currentTask := task.Current() currentTask := task.Current()
frame.Previous = (*deferFrame)(currentTask.DeferFrame) frame.Previous = (*deferFrameInlineAsm)(currentTask.DeferFrame)
frame.JumpSP = jumpSP frame.JumpSP = jumpSP
frame.Panicking = false frame.Panicking = false
currentTask.DeferFrame = unsafe.Pointer(frame) currentTask.DeferFrame = unsafe.Pointer(frame)
} }
//go:inline
//go:nobounds
func setupDeferFrameWasmEH(frame *deferFrameWasmEH) {
currentTask := task.Current()
frame.Previous = (*deferFrameWasmEH)(currentTask.DeferFrame)
frame.Panicking = false
currentTask.DeferFrame = unsafe.Pointer(frame)
}
// Called right before the return instruction. It pops the defer frame from the // Called right before the return instruction. It pops the defer frame from the
// linked list of defer frames. It also re-raises a panic if the goroutine is // linked list of defer frames. It also re-raises a panic if the goroutine is
// still panicking. // still panicking.
// //
//go:inline //go:inline
//go:nobounds //go:nobounds
func destroyDeferFrame(frame *deferFrame) { func destroyDeferFrameInlineAsm(frame *deferFrameInlineAsm) {
task.Current().DeferFrame = unsafe.Pointer(frame.Previous)
if frame.Panicking {
// We're still panicking!
// Re-raise the panic now.
_panic(frame.PanicValue)
}
}
// Like destroyDeferFrameInlineAsm but for wasm.
//
//go:inline
//go:nobounds
func destroyDeferFrameWasmEH(frame *deferFrameWasmEH) {
task.Current().DeferFrame = unsafe.Pointer(frame.Previous) task.Current().DeferFrame = unsafe.Pointer(frame.Previous)
if frame.Panicking { if frame.Panicking {
// We're still panicking! // We're still panicking!
@@ -122,27 +175,44 @@ func destroyDeferFrame(frame *deferFrame) {
// useParentFrame is set when the caller of runtime._recover has a defer frame // useParentFrame is set when the caller of runtime._recover has a defer frame
// itself. In that case, recover() shouldn't check that frame but one frame up. // itself. In that case, recover() shouldn't check that frame but one frame up.
func _recover(useParentFrame bool) interface{} { func _recover(useParentFrame bool) interface{} {
if !supportsRecover() {
// Compiling without stack unwinding support, so make this a no-op.
return nil
}
// TODO: somehow check that recover() is called directly by a deferred // TODO: somehow check that recover() is called directly by a deferred
// function in a panicking goroutine. Maybe this can be done by comparing // function in a panicking goroutine. Maybe this can be done by comparing
// the frame pointer? // the frame pointer?
frame := (*deferFrame)(task.Current().DeferFrame) switch supportsRecover() {
if useParentFrame { case recoverInlineAsm:
// Don't recover panic from the current frame (which can't be panicking frame := (*deferFrameInlineAsm)(task.Current().DeferFrame)
// already), but instead from the previous frame. if useParentFrame {
frame = frame.Previous // Don't recover panic from the current frame (which can't be
// panicking already), but instead from the previous frame.
frame = frame.Previous
}
if frame != nil && frame.Panicking {
// Only the first call to recover returns the panic value. It also
// stops the panicking sequence, hence setting panicking to false.
frame.Panicking = false
return frame.PanicValue
}
// Not panicking, so return a nil interface.
return nil
case recoverWasmEH:
frame := (*deferFrameWasmEH)(task.Current().DeferFrame)
if useParentFrame {
// Don't recover panic from the current frame (which can't be
// panicking already), but instead from the previous frame.
frame = frame.Previous
}
if frame != nil && frame.Panicking {
// Only the first call to recover returns the panic value. It also
// stops the panicking sequence, hence setting panicking to false.
frame.Panicking = false
return frame.PanicValue
}
// Not panicking, so return a nil interface.
return nil
default:
// Compiling without stack unwinding support, so make this a no-op.
return nil
} }
if frame != nil && frame.Panicking {
// Only the first call to recover returns the panic value. It also stops
// the panicking sequence, hence setting panicking to false.
frame.Panicking = false
return frame.PanicValue
}
// Not panicking, so return a nil interface.
return nil
} }
// Panic when trying to dereference a nil pointer. // Panic when trying to dereference a nil pointer.
+2 -1
View File
@@ -1,7 +1,7 @@
{ {
"llvm-target": "wasm32-unknown-wasi", "llvm-target": "wasm32-unknown-wasi",
"cpu": "generic", "cpu": "generic",
"features": "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext", "features": "+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext",
"build-tags": ["tinygo.wasm"], "build-tags": ["tinygo.wasm"],
"goos": "js", "goos": "js",
"goarch": "wasm", "goarch": "wasm",
@@ -12,6 +12,7 @@
"default-stack-size": 65536, "default-stack-size": 65536,
"cflags": [ "cflags": [
"-mbulk-memory", "-mbulk-memory",
"-mexception-handling",
"-mnontrapping-fptoint", "-mnontrapping-fptoint",
"-msign-ext" "-msign-ext"
], ],
+27
View File
@@ -17,6 +17,12 @@ func main() {
println("\n# panic inside defer") println("\n# panic inside defer")
panicInsideDefer() panicInsideDefer()
println("\n# panic inside indirect defer")
panicInsideIndirectDefer(callPanic)
println("\n# panic inside closure")
panicInsideClosure()
println("\n# panic replace") println("\n# panic replace")
panicReplace() panicReplace()
} }
@@ -77,6 +83,27 @@ func panicInsideDefer() {
}() }()
} }
func panicInsideIndirectDefer(callback func()) {
defer func() {
printitf("recovered:", recover())
}()
defer callback()
}
func callPanic() {
panic("panic")
}
func panicInsideClosure() {
msg := "panic"
defer func() {
printitf("recovered:", recover())
}()
defer func() {
panic(msg)
}()
}
func panicReplace() { func panicReplace() {
defer func() { defer func() {
printitf("recovered:", recover()) printitf("recovered:", recover())
+6
View File
@@ -19,6 +19,12 @@ recovered 2: foo
# panic inside defer # panic inside defer
recovered: panic recovered: panic
# panic inside indirect defer
recovered: panic
# panic inside closure
recovered: panic
# panic replace # panic replace
panic 1 panic 1
panic 2 panic 2
+1 -1
View File
@@ -177,7 +177,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
// now. // now.
// With more analysis, it should be possible to optimize a // With more analysis, it should be possible to optimize a
// significant chunk of these away. // significant chunk of these away.
case llvm.Call, llvm.Load, llvm.IntToPtr: case llvm.Call, llvm.Invoke, llvm.Load, llvm.IntToPtr:
// These create new values so must be stored locally. But // These create new values so must be stored locally. But
// perhaps some of these can be fused when they actually refer // perhaps some of these can be fused when they actually refer
// to the same value. // to the same value.