aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNia Waldvogel <[email protected]>2021-09-17 12:23:01 -0400
committerAyke <[email protected]>2021-09-21 20:08:30 +0200
commit157382600535c95bdbf5d6e8c4b9e5ca71749018 (patch)
treeee2866f936f9fe315b176fd9430e44edc664ba0f
parentecd8c2d902498c9b3c39417b9e52e8844adcb1cd (diff)
downloadtinygo-157382600535c95bdbf5d6e8c4b9e5ca71749018.tar.gz
tinygo-157382600535c95bdbf5d6e8c4b9e5ca71749018.zip
transform (coroutines): move any misplaced entry-block allocas to the start of the entry block before loweringv0.20.0
-rw-r--r--transform/coroutines.go21
1 files changed, 21 insertions, 0 deletions
diff --git a/transform/coroutines.go b/transform/coroutines.go
index 9a382c3ae..e1f109b1b 100644
--- a/transform/coroutines.go
+++ b/transform/coroutines.go
@@ -763,6 +763,27 @@ func (c *coroutineLoweringPass) lowerCallReturn(caller *asyncFunc, call llvm.Val
// lowerFuncCoro transforms an async function into a coroutine by lowering async operations to `llvm.coro` intrinsics.
// See https://llvm.org/docs/Coroutines.html for more information on these intrinsics.
func (c *coroutineLoweringPass) lowerFuncCoro(fn *asyncFunc) {
+ // Ensure that any alloca instructions in the entry block are at the start.
+ // Otherwise, block splitting would result in unintended behavior.
+ {
+ // Skip alloca instructions at the start of the block.
+ inst := fn.fn.FirstBasicBlock().FirstInstruction()
+ for !inst.IsAAllocaInst().IsNil() {
+ inst = llvm.NextInstruction(inst)
+ }
+
+ // Find any other alloca instructions and move them after the other allocas.
+ c.builder.SetInsertPointBefore(inst)
+ for !inst.IsNil() {
+ next := llvm.NextInstruction(inst)
+ if !inst.IsAAllocaInst().IsNil() {
+ inst.RemoveFromParentAsInstruction()
+ c.builder.Insert(inst)
+ }
+ inst = next
+ }
+ }
+
returnType := fn.fn.Type().ElementType().ReturnType()
// Prepare coroutine state.