}
// const* routines add a new const value to the entry block.
+func (s *state) constSlice(t ssa.Type) *ssa.Value { return s.f.ConstSlice(s.peekLine(), t) }
+func (s *state) constInterface(t ssa.Type) *ssa.Value { return s.f.ConstInterface(s.peekLine(), t) }
+func (s *state) constNil(t ssa.Type) *ssa.Value { return s.f.ConstNil(s.peekLine(), t) }
+func (s *state) constEmptyString(t ssa.Type) *ssa.Value { return s.f.ConstEmptyString(s.peekLine(), t) }
func (s *state) constBool(c bool) *ssa.Value {
return s.f.ConstBool(s.peekLine(), Types[TBOOL], c)
}
return nil
}
case CTSTR:
+ if n.Val().U == "" {
+ return s.constEmptyString(n.Type)
+ }
return s.entryNewValue0A(ssa.OpConstString, n.Type, n.Val().U)
case CTBOOL:
v := s.constBool(n.Val().U.(bool))
t := n.Type
switch {
case t.IsSlice():
- return s.entryNewValue0(ssa.OpConstSlice, t)
+ return s.constSlice(t)
case t.IsInterface():
- return s.entryNewValue0(ssa.OpConstInterface, t)
+ return s.constInterface(t)
default:
- return s.entryNewValue0(ssa.OpConstNil, t)
+ return s.constNil(t)
}
case CTFLT:
f := n.Val().U.(*Mpflt)
}
case t.IsString():
- return s.entryNewValue0A(ssa.OpConstString, t, "")
+ return s.constEmptyString(t)
case t.IsPtr():
- return s.entryNewValue0(ssa.OpConstNil, t)
+ return s.constNil(t)
case t.IsBoolean():
return s.constBool(false)
case t.IsInterface():
- return s.entryNewValue0(ssa.OpConstInterface, t)
+ return s.constInterface(t)
case t.IsSlice():
- return s.entryNewValue0(ssa.OpConstSlice, t)
+ return s.constSlice(t)
case t.IsStruct():
n := t.NumFields()
v := s.entryNewValue0(ssa.StructMakeOp(t.NumFields()), t)
// return *(((*int)n)+1)
// }
lenType := n.Type
- nilValue := s.newValue0(ssa.OpConstNil, Types[TUINTPTR])
+ nilValue := s.constNil(Types[TUINTPTR])
cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue)
b := s.endBlock()
b.Kind = ssa.BlockIf
tab := s.newValue1(ssa.OpITab, byteptr, v)
s.vars[&typVar] = tab
- isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.entryNewValue0(ssa.OpConstNil, byteptr))
+ isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.constNil(byteptr))
b := s.endBlock()
b.Kind = ssa.BlockIf
b.Control = isnonnil
// type assertion failed
s.startBlock(bFail)
- s.vars[&idataVar] = s.entryNewValue0(ssa.OpConstNil, byteptr)
+ s.vars[&idataVar] = s.constNil(byteptr)
s.vars[&okVar] = s.constBool(false)
s.endBlock()
bFail.AddEdgeTo(bEnd)
}
// constVal returns a constant value for c.
-func (f *Func) constVal(line int32, op Op, t Type, c int64) *Value {
+func (f *Func) constVal(line int32, op Op, t Type, c int64, setAux bool) *Value {
if f.constants == nil {
f.constants = make(map[int64][]*Value)
}
return v
}
}
- v := f.Entry.NewValue0I(line, op, t, c)
+ var v *Value
+ if setAux {
+ v = f.Entry.NewValue0I(line, op, t, c)
+ } else {
+ v = f.Entry.NewValue0(line, op, t)
+ }
f.constants[c] = append(vv, v)
return v
}
+// These magic auxint values let us easily cache non-numeric constants
+// using the same constants map while making collisions unlikely.
+// These values are unlikely to occur in regular code and
+// are easy to grep for in case of bugs.
+const (
+ constSliceMagic = 1122334455
+ constInterfaceMagic = 2233445566
+ constNilMagic = 3344556677
+ constEmptyStringMagic = 4455667788
+)
+
// ConstInt returns an int constant representing its argument.
func (f *Func) ConstBool(line int32, t Type, c bool) *Value {
i := int64(0)
if c {
i = 1
}
- return f.constVal(line, OpConstBool, t, i)
+ return f.constVal(line, OpConstBool, t, i, true)
}
func (f *Func) ConstInt8(line int32, t Type, c int8) *Value {
- return f.constVal(line, OpConst8, t, int64(c))
+ return f.constVal(line, OpConst8, t, int64(c), true)
}
func (f *Func) ConstInt16(line int32, t Type, c int16) *Value {
- return f.constVal(line, OpConst16, t, int64(c))
+ return f.constVal(line, OpConst16, t, int64(c), true)
}
func (f *Func) ConstInt32(line int32, t Type, c int32) *Value {
- return f.constVal(line, OpConst32, t, int64(c))
+ return f.constVal(line, OpConst32, t, int64(c), true)
}
func (f *Func) ConstInt64(line int32, t Type, c int64) *Value {
- return f.constVal(line, OpConst64, t, c)
+ return f.constVal(line, OpConst64, t, c, true)
}
func (f *Func) ConstFloat32(line int32, t Type, c float64) *Value {
- return f.constVal(line, OpConst32F, t, int64(math.Float64bits(c)))
+ return f.constVal(line, OpConst32F, t, int64(math.Float64bits(c)), true)
}
func (f *Func) ConstFloat64(line int32, t Type, c float64) *Value {
- return f.constVal(line, OpConst64F, t, int64(math.Float64bits(c)))
+ return f.constVal(line, OpConst64F, t, int64(math.Float64bits(c)), true)
+}
+
+func (f *Func) ConstSlice(line int32, t Type) *Value {
+ return f.constVal(line, OpConstSlice, t, constSliceMagic, false)
+}
+func (f *Func) ConstInterface(line int32, t Type) *Value {
+ return f.constVal(line, OpConstInterface, t, constInterfaceMagic, false)
+}
+func (f *Func) ConstNil(line int32, t Type) *Value {
+ return f.constVal(line, OpConstNil, t, constNilMagic, false)
+}
+func (f *Func) ConstEmptyString(line int32, t Type) *Value {
+ v := f.constVal(line, OpConstString, t, constEmptyStringMagic, false)
+ v.Aux = ""
+ return v
}
func (f *Func) Logf(msg string, args ...interface{}) { f.Config.Logf(msg, args...) }