diff options
author | Ayke van Laethem <[email protected]> | 2019-05-24 13:43:34 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2019-05-24 14:00:23 +0200 |
commit | 7156afca9e4e81b069780170acdbb78d10050d09 (patch) | |
tree | 359258d259ac66f6118cbb0a3f5f141ec9e0484c | |
parent | 87ac804642d0ac61cc7fe55e6b3126425e523ae3 (diff) | |
download | tinygo-7156afca9e4e81b069780170acdbb78d10050d09.tar.gz tinygo-7156afca9e4e81b069780170acdbb78d10050d09.zip |
interp: support some more expressions in const icmp
-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 +} |