aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJaden Weiss <[email protected]>2019-10-05 21:43:27 -0400
committerAyke <[email protected]>2019-10-16 16:04:37 +0200
commit8906192690d71392c46ad56cffb7d4ce6b6e5529 (patch)
treea46fb105caff95c3fff88dddce2715b3c9a1e233
parent20a55e79441ef224b92e17a1e4b621e67021e506 (diff)
downloadtinygo-8906192690d71392c46ad56cffb7d4ce6b6e5529.tar.gz
tinygo-8906192690d71392c46ad56cffb7d4ce6b6e5529.zip
fix goroutine lowering type errors
-rw-r--r--compiler/goroutine-lowering.go20
-rw-r--r--compiler/llvm.go16
2 files changed, 22 insertions, 14 deletions
diff --git a/compiler/goroutine-lowering.go b/compiler/goroutine-lowering.go
index 45465b2f8..5641a6ed8 100644
--- a/compiler/goroutine-lowering.go
+++ b/compiler/goroutine-lowering.go
@@ -450,8 +450,6 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
}
coroDebugPrintln("scanning", f.Name())
- var retAlloc llvm.Value
-
// Rewrite async calls
for bb := f.EntryBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {
for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {
@@ -511,9 +509,9 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
// pass parent handle directly into function
inst.SetOperand(inst.OperandsCount()-2, parentHandle)
- if inst.Type().TypeKind() != llvm.VoidTypeKind {
+ if callee.Type().ElementType().ReturnType().TypeKind() != llvm.VoidTypeKind {
// delete return value
- uses[0].SetOperand(0, llvm.Undef(inst.Type()))
+ uses[0].SetOperand(0, llvm.Undef(callee.Type().ElementType().ReturnType()))
}
c.builder.SetInsertPointBefore(next)
@@ -534,15 +532,9 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
// Allocate space for the return value.
var retvalAlloca llvm.Value
- if inst.Type().TypeKind() != llvm.VoidTypeKind {
- if retAlloc.IsNil() {
- // insert at start of function
- c.builder.SetInsertPointBefore(f.EntryBasicBlock().FirstInstruction())
-
- // allocate return value buffer
- retAlloc = c.builder.CreateAlloca(inst.Type(), "coro.retvalAlloca")
- }
- retvalAlloca = retAlloc
+ if callee.Type().ElementType().ReturnType().TypeKind() != llvm.VoidTypeKind {
+ // allocate return value buffer
+ retvalAlloca = c.createInstructionAlloca(callee.Type().ElementType().ReturnType(), inst, "coro.retvalAlloca")
// call before function
c.builder.SetInsertPointBefore(inst)
@@ -672,7 +664,7 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
c.builder.CreateStore(inst.Operand(0), retPtr)
// delete return value
- inst.SetOperand(0, llvm.Undef(inst.Type()))
+ inst.SetOperand(0, llvm.Undef(f.Type().ElementType().ReturnType()))
}
// insert reactivation call
diff --git a/compiler/llvm.go b/compiler/llvm.go
index 747edabbd..2df6d2768 100644
--- a/compiler/llvm.go
+++ b/compiler/llvm.go
@@ -54,6 +54,22 @@ func (c *Compiler) createTemporaryAlloca(t llvm.Type, name string) (alloca, bitc
return
}
+// createInstructionAlloca creates an alloca in the entry block, and places lifetime control intrinsics around the instruction
+func (c *Compiler) createInstructionAlloca(t llvm.Type, inst llvm.Value, name string) llvm.Value {
+ alloca := c.createEntryBlockAlloca(t, name)
+ c.builder.SetInsertPointBefore(inst)
+ bitcast := c.builder.CreateBitCast(alloca, c.i8ptrType, name+".bitcast")
+ size := llvm.ConstInt(c.ctx.Int64Type(), c.targetData.TypeAllocSize(t), false)
+ c.builder.CreateCall(c.getLifetimeStartFunc(), []llvm.Value{size, bitcast}, "")
+ if next := llvm.NextInstruction(inst); !next.IsNil() {
+ c.builder.SetInsertPointBefore(next)
+ } else {
+ c.builder.SetInsertPointAtEnd(inst.InstructionParent())
+ }
+ c.builder.CreateCall(c.getLifetimeEndFunc(), []llvm.Value{size, bitcast}, "")
+ return alloca
+}
+
// emitLifetimeEnd signals the end of an (alloca) lifetime by calling the
// llvm.lifetime.end intrinsic. It is commonly used together with
// createTemporaryAlloca.