interp: make errors during branches more reliable

Previously, there was a suble error in that .IsConstant() is not always
allowed to be called, resulting in a i1 that was not 0 or 1. Fix this by
checking for the constants directly and adding some more diagnostics to
catch more cases.
Этот коммит содержится в:
Ayke van Laethem 2019-05-21 17:40:03 +02:00 коммит произвёл Ron Evans
родитель e4d53daa02
коммит f1d9e7b75e

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

@ -461,17 +461,21 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
} }
thenBB := inst.Operand(1) thenBB := inst.Operand(1)
elseBB := inst.Operand(2) elseBB := inst.Operand(2)
if !cond.IsConstant() { if !cond.IsAInstruction().IsNil() {
return nil, nil, errors.New("interp: branch on a non-constant") return nil, nil, errors.New("interp: branch on a non-constant")
} else { }
switch cond.ZExtValue() { if !cond.IsAConstantExpr().IsNil() {
case 0: // false // This may happen when the instruction builder could not
return nil, []llvm.Value{thenBB}, nil // then // const-fold some instructions.
case 1: // true return nil, nil, errors.New("interp: branch on a non-const-propagated constant expression")
return nil, []llvm.Value{elseBB}, nil // else }
default: switch cond {
panic("branch was not true or false") case llvm.ConstInt(fr.Mod.Context().Int1Type(), 0, false): // false
} return nil, []llvm.Value{thenBB}, nil // then
case llvm.ConstInt(fr.Mod.Context().Int1Type(), 1, false): // true
return nil, []llvm.Value{elseBB}, nil // else
default:
panic("branch was not true or false")
} }
case !inst.IsABranchInst().IsNil() && inst.OperandsCount() == 1: case !inst.IsABranchInst().IsNil() && inst.OperandsCount() == 1:
// unconditional branch (goto) // unconditional branch (goto)