diff options
author | Ayke van Laethem <[email protected]> | 2019-12-07 22:12:27 +0100 |
---|---|---|
committer | Ayke <[email protected]> | 2020-02-24 23:11:07 +0100 |
commit | 4da137d7c88cb96ccae5ebb6bca75065c7c9a3f7 (patch) | |
tree | 471ecb84b1aab892f048a5f3bd12093cdc6049a4 /compiler | |
parent | c622cbac398c94327e7d4bfd261badd10db1ad6c (diff) | |
download | tinygo-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.go | 18 |
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 { |