aboutsummaryrefslogtreecommitdiffhomepage
path: root/transform
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-12-07 23:09:55 +0100
committerRon Evans <[email protected]>2020-01-28 19:29:09 +0100
commit519adf3aefdbaaac93b0216b61988ba6c29a0546 (patch)
tree67748fb320ce3c53e61c847a2ba3d7274135ee1b /transform
parent4d79d473c40269c6529f0a3f03d176726483e4d8 (diff)
downloadtinygo-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.ll4
-rw-r--r--transform/wasm-abi.go10
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 {