diff options
author | Ayke van Laethem <[email protected]> | 2019-12-07 23:09:55 +0100 |
---|---|---|
committer | Ron Evans <[email protected]> | 2020-01-28 19:29:09 +0100 |
commit | 519adf3aefdbaaac93b0216b61988ba6c29a0546 (patch) | |
tree | 67748fb320ce3c53e61c847a2ba3d7274135ee1b /transform | |
parent | 4d79d473c40269c6529f0a3f03d176726483e4d8 (diff) | |
download | tinygo-519adf3aefdbaaac93b0216b61988ba6c29a0546.tar.gz tinygo-519adf3aefdbaaac93b0216b61988ba6c29a0546.zip |
transform: wasm-abi: create temporary allocas in the entry block
This avoids problems with goroutines in WebAssembly, and is generally a
good thing. It fixes some cases of the following problem:
LLVM ERROR: Coroutines cannot handle non static allocas yet
Diffstat (limited to 'transform')
-rw-r--r-- | transform/testdata/wasm-abi.out.ll | 4 | ||||
-rw-r--r-- | transform/wasm-abi.go | 10 |
2 files changed, 10 insertions, 4 deletions
diff --git a/transform/testdata/wasm-abi.out.ll b/transform/testdata/wasm-abi.out.ll index bc69ffbba..6fb9a9482 100644 --- a/transform/testdata/wasm-abi.out.ll +++ b/transform/testdata/wasm-abi.out.ll @@ -14,11 +14,11 @@ define internal i64 @testCall(i8* %ptr, i32 %len, i64 %foo) { define internal i64 @testCallNonEntry(i8* %ptr, i32 %len) { entry: + %i64asptr = alloca i64 + %i64asptr1 = alloca i64 br label %bb1 bb1: ; preds = %entry - %i64asptr = alloca i64 - %i64asptr1 = alloca i64 store i64 3, i64* %i64asptr1 call void @externalCall(i64* %i64asptr, i8* %ptr, i32 %len, i64* %i64asptr1) %retval = load i64, i64* %i64asptr diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go index 1d167b51b..0c3af9a3d 100644 --- a/transform/wasm-abi.go +++ b/transform/wasm-abi.go @@ -22,6 +22,11 @@ func ExternalInt64AsPtr(mod llvm.Module) error { int64Type := ctx.Int64Type() int64PtrType := llvm.PointerType(int64Type, 0) + // This builder is only used for creating new allocas in the entry block of + // a function, avoiding many SetInsertPoint* calls. + entryBlockBuilder := ctx.NewBuilder() + defer entryBlockBuilder.Dispose() + for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { if fn.Linkage() != llvm.ExternalLinkage { // Only change externally visible functions (exports and imports). @@ -77,11 +82,12 @@ func ExternalInt64AsPtr(mod llvm.Module) error { // be left in place. for use := fn.FirstUse(); !use.IsNil(); use = use.NextUse() { call := use.User() + entryBlockBuilder.SetInsertPointBefore(call.InstructionParent().Parent().EntryBasicBlock().FirstInstruction()) builder.SetInsertPointBefore(call) callParams := []llvm.Value{} var retvalAlloca llvm.Value if fnType.ReturnType() == int64Type { - retvalAlloca = builder.CreateAlloca(int64Type, "i64asptr") + retvalAlloca = entryBlockBuilder.CreateAlloca(int64Type, "i64asptr") callParams = append(callParams, retvalAlloca) } for i := 0; i < call.OperandsCount()-1; i++ { @@ -89,7 +95,7 @@ func ExternalInt64AsPtr(mod llvm.Module) error { if operand.Type() == int64Type { // Pass a stack-allocated pointer instead of the value // itself. - alloca := builder.CreateAlloca(int64Type, "i64asptr") + alloca := entryBlockBuilder.CreateAlloca(int64Type, "i64asptr") builder.CreateStore(operand, alloca) callParams = append(callParams, alloca) } else { |