interp: use correct initialization order on panic() calls

Whenever interp hits an unreachable instruction, it bails out at that
point. However, it used to insert new instructions at the bottom with
the old init calls still at the top. So when a panic() happened in a
non-main package, the last packages to init would actually be called
first.

This commit fixes this by setting the insert point at the top of
runtime.initAll before starting interpretation, so the initialization
order is still correct when a panic() happens during init.
Этот коммит содержится в:
Ayke van Laethem 2019-03-07 15:05:25 +01:00 коммит произвёл Ron Evans
родитель 4ad9bd8643
коммит cfc1a66e8d

Просмотреть файл

@ -42,10 +42,19 @@ func Run(mod llvm.Module, targetData llvm.TargetData, debug bool) error {
initAll := mod.NamedFunction(name) initAll := mod.NamedFunction(name)
bb := initAll.EntryBasicBlock() bb := initAll.EntryBasicBlock()
e.builder.SetInsertPointBefore(bb.LastInstruction()) // Create a dummy alloca in the entry block that we can set the insert point
// to. This is necessary because otherwise we might be removing the
// instruction (init call) that we are removing after successful
// interpretation.
e.builder.SetInsertPointBefore(bb.FirstInstruction())
dummy := e.builder.CreateAlloca(e.Mod.Context().Int8Type(), "dummy")
e.builder.SetInsertPointBefore(dummy)
e.builder.SetInstDebugLocation(bb.FirstInstruction()) e.builder.SetInstDebugLocation(bb.FirstInstruction())
var initCalls []llvm.Value var initCalls []llvm.Value
for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) { for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {
if inst == dummy {
continue
}
if !inst.IsAReturnInst().IsNil() { if !inst.IsAReturnInst().IsNil() {
break // ret void break // ret void
} }