diff options
-rw-r--r-- | interp/frame.go | 19 | ||||
-rw-r--r-- | interp/utils.go | 26 |
2 files changed, 28 insertions, 17 deletions
diff --git a/interp/frame.go b/interp/frame.go index 9971c0a1e..60d2cb7c9 100644 --- a/interp/frame.go +++ b/interp/frame.go @@ -188,23 +188,8 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re // Unfortunately, the const propagation in the IR builder // doesn't handle pointer compares of inttoptr values. So we // implement it manually here. - isNil := func(v llvm.Value) (result bool, ok bool) { - if !v.IsAConstantExpr().IsNil() && v.Opcode() == llvm.IntToPtr { - // Whether a constant inttoptr is nil is easy to - // determine. - operand := v.Operand(0) - if operand.IsConstant() { - return operand.ZExtValue() == 0, true - } - } - if !v.IsAConstantPointerNull().IsNil() { - // A constant pointer null is always null, of course. - return true, true - } - return false, false // not valid - } - lhsNil, ok1 := isNil(lhs) - rhsNil, ok2 := isNil(rhs) + lhsNil, ok1 := isPointerNil(lhs) + rhsNil, ok2 := isPointerNil(rhs) if ok1 && ok2 { if lhsNil && rhsNil { // Both are nil, so this icmp is always evaluated to true. diff --git a/interp/utils.go b/interp/utils.go index 3d0d3ba6d..7910ea8a7 100644 --- a/interp/utils.go +++ b/interp/utils.go @@ -94,3 +94,29 @@ func isScalar(t llvm.Type) bool { return false } } + +// isPointerNil returns whether this is a nil pointer or not. The ok value +// indicates whether the result is certain: if it is false the result boolean is +// not valid. +func isPointerNil(v llvm.Value) (result bool, ok bool) { + if !v.IsAConstantExpr().IsNil() { + switch v.Opcode() { + case llvm.IntToPtr: + // Whether a constant inttoptr is nil is easy to + // determine. + operand := v.Operand(0) + if operand.IsConstant() { + return operand.ZExtValue() == 0, true + } + case llvm.BitCast, llvm.GetElementPtr: + // These const instructions are just a kind of wrappers for the + // underlying pointer. + return isPointerNil(v.Operand(0)) + } + } + if !v.IsAConstantPointerNull().IsNil() { + // A constant pointer null is always null, of course. + return true, true + } + return false, false // not valid +} |