From f1d9e7b75e5035606c12e981d4d4ee4ca195fa22 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Tue, 21 May 2019 17:40:03 +0200 Subject: [PATCH] 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. --- interp/frame.go | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/interp/frame.go b/interp/frame.go index 7e280b87..0180ff7f 100644 --- a/interp/frame.go +++ b/interp/frame.go @@ -461,17 +461,21 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re } thenBB := inst.Operand(1) elseBB := inst.Operand(2) - if !cond.IsConstant() { + if !cond.IsAInstruction().IsNil() { return nil, nil, errors.New("interp: branch on a non-constant") - } else { - switch cond.ZExtValue() { - case 0: // false - return nil, []llvm.Value{thenBB}, nil // then - case 1: // true - return nil, []llvm.Value{elseBB}, nil // else - default: - panic("branch was not true or false") - } + } + if !cond.IsAConstantExpr().IsNil() { + // This may happen when the instruction builder could not + // const-fold some instructions. + return nil, nil, errors.New("interp: branch on a non-const-propagated constant expression") + } + switch cond { + 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: // unconditional branch (goto)