aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--interp/frame.go19
-rw-r--r--interp/utils.go26
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
+}