aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-12-07 22:12:27 +0100
committerAyke <[email protected]>2020-02-24 23:11:07 +0100
commit4da137d7c88cb96ccae5ebb6bca75065c7c9a3f7 (patch)
tree471ecb84b1aab892f048a5f3bd12093cdc6049a4 /compiler
parentc622cbac398c94327e7d4bfd261badd10db1ad6c (diff)
downloadtinygo-4da137d7c88cb96ccae5ebb6bca75065c7c9a3f7.tar.gz
tinygo-4da137d7c88cb96ccae5ebb6bca75065c7c9a3f7.zip
compiler: check for non-static allocas
Non-static allocas are disallowed for a number of reasons, so check for their presence. See the commit diff for details.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/check.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/compiler/check.go b/compiler/check.go
index 8be5c702a..5372b1efc 100644
--- a/compiler/check.go
+++ b/compiler/check.go
@@ -101,6 +101,24 @@ func (c *Compiler) checkInstruction(inst llvm.Value, types map[llvm.Type]struct{
return errorAt(inst, err.Error())
}
+ // The alloca instruction can be present in every basic block. However,
+ // allocas in basic blocks other than the entry basic block have a number of
+ // problems:
+ // * They are hard to optimize, leading to potential missed optimizations.
+ // * They may cause stack overflows in loops that would otherwise be
+ // innocent.
+ // * They cause extra code to be generated, because it requires the use of
+ // a frame pointer.
+ // * Perhaps most importantly, the coroutine lowering pass of LLVM (as of
+ // LLVM 9) cannot deal with these allocas:
+ // https://llvm.org/docs/Coroutines.html
+ // Therefore, alloca instructions should be limited to the entry block.
+ if !inst.IsAAllocaInst().IsNil() {
+ if inst.InstructionParent() != inst.InstructionParent().Parent().EntryBasicBlock() {
+ return errorAt(inst, "internal error: non-static alloca")
+ }
+ }
+
// check operands
for i := 0; i < inst.OperandsCount(); i++ {
if err := c.checkValue(inst.Operand(i), types, specials); err != nil {