addr := s.decladdrs[n]
val := s.variable(n, n.Type)
s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, n, s.mem())
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, n.Type.Size(), addr, val, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, n.Type.Size(), addr, val, s.mem())
+ store.Aux = n.Type
+ s.vars[&memVar] = store
// TODO: if val is ever spilled, we'd like to use the
// PPARAMOUT slot for spilling it. That won't happen
// currently.
s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, sn, s.mem())
}
capaddr := s.newValue1I(ssa.OpOffPtr, ptrto(Types[TINT]), int64(array_cap), addr)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, capaddr, r[2], s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, capaddr, r[2], s.mem())
+ store.Aux = Types[TINT]
+ s.vars[&memVar] = store
if ssa.IsStackAddr(addr) {
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, pt.Size(), addr, r[0], s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, pt.Size(), addr, r[0], s.mem())
+ store.Aux = pt
+ s.vars[&memVar] = store
} else {
s.insertWBstore(pt, addr, r[0], 0)
}
l = s.variable(&lenVar, Types[TINT]) // generates phi for len
nl = s.newValue2(s.ssaOp(OADD, Types[TINT]), Types[TINT], l, s.constInt(Types[TINT], nargs))
lenaddr := s.newValue1I(ssa.OpOffPtr, ptrto(Types[TINT]), int64(array_nel), addr)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenaddr, nl, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenaddr, nl, s.mem())
+ store.Aux = Types[TINT]
+ s.vars[&memVar] = store
}
// Evaluate args
if haspointers(et) {
s.insertWBstore(et, addr, arg.v, 0)
} else {
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, et.Size(), addr, arg.v, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, et.Size(), addr, arg.v, s.mem())
+ store.Aux = et
+ s.vars[&memVar] = store
}
} else {
if haspointers(et) {
s.insertWBmove(et, addr, arg.v)
} else {
- s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, sizeAlignAuxInt(et), addr, arg.v, s.mem())
+ store := s.newValue3I(ssa.OpMove, ssa.TypeMem, sizeAlignAuxInt(et), addr, arg.v, s.mem())
+ store.Aux = et
+ s.vars[&memVar] = store
}
}
}
return
}
if right == nil {
- s.vars[&memVar] = s.newValue2I(ssa.OpZero, ssa.TypeMem, sizeAlignAuxInt(t), addr, s.mem())
+ store := s.newValue2I(ssa.OpZero, ssa.TypeMem, sizeAlignAuxInt(t), addr, s.mem())
+ store.Aux = t
+ s.vars[&memVar] = store
return
}
- s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, sizeAlignAuxInt(t), addr, right, s.mem())
+ store := s.newValue3I(ssa.OpMove, ssa.TypeMem, sizeAlignAuxInt(t), addr, right, s.mem())
+ store.Aux = t
+ s.vars[&memVar] = store
return
}
// Treat as a store.
s.storeTypeScalars(t, addr, right, skip)
return
}
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), addr, right, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), addr, right, s.mem())
+ store.Aux = t
+ s.vars[&memVar] = store
}
// zeroVal returns the zero value for type t.
argStart += int64(2 * Widthptr)
}
addr := s.constOffPtrSP(ptrto(Types[TUINTPTR]), argStart)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, rcvr, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, rcvr, s.mem())
+ store.Aux = Types[TUINTPTR]
+ s.vars[&memVar] = store
}
// Defer/go args
argStart := Ctxt.FixedFrameSize()
argsize := s.constInt32(Types[TUINT32], int32(stksize))
addr := s.constOffPtrSP(ptrto(Types[TUINT32]), argStart)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, 4, addr, argsize, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, 4, addr, argsize, s.mem())
+ store.Aux = Types[TUINT32]
+ s.vars[&memVar] = store
addr = s.constOffPtrSP(ptrto(Types[TUINTPTR]), argStart+int64(Widthptr))
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, closure, s.mem())
+ store = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, closure, s.mem())
+ store.Aux = Types[TUINTPTR]
+ s.vars[&memVar] = store
stksize += 2 * int64(Widthptr)
}
off = Rnd(off, t.Alignment())
ptr := s.constOffPtrSP(t.PtrTo(), off)
size := t.Size()
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, size, ptr, arg, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, size, ptr, arg, s.mem())
+ store.Aux = t
+ s.vars[&memVar] = store
off += size
}
off = Rnd(off, int64(Widthptr))
} else {
val = s.newValue3I(ssa.OpMoveWB, ssa.TypeMem, sizeAlignAuxInt(t), left, right, s.mem())
}
- val.Aux = &ssa.ExternSymbol{Typ: Types[TUINTPTR], Sym: Linksym(typenamesym(t))}
+ //val.Aux = &ssa.ExternSymbol{Typ: Types[TUINTPTR], Sym: Linksym(typenamesym(t))}
+ val.Aux = t
s.vars[&memVar] = val
}
func (s *state) storeTypeScalars(t *Type, left, right *ssa.Value, skip skipMask) {
switch {
case t.IsBoolean() || t.IsInteger() || t.IsFloat() || t.IsComplex():
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), left, right, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), left, right, s.mem())
+ store.Aux = t
+ s.vars[&memVar] = store
case t.IsPtrShaped():
// no scalar fields.
case t.IsString():
}
len := s.newValue1(ssa.OpStringLen, Types[TINT], right)
lenAddr := s.newValue1I(ssa.OpOffPtr, ptrto(Types[TINT]), s.config.IntSize, left)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenAddr, len, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenAddr, len, s.mem())
+ store.Aux = Types[TINT]
+ s.vars[&memVar] = store
case t.IsSlice():
if skip&skipLen == 0 {
len := s.newValue1(ssa.OpSliceLen, Types[TINT], right)
lenAddr := s.newValue1I(ssa.OpOffPtr, ptrto(Types[TINT]), s.config.IntSize, left)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenAddr, len, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenAddr, len, s.mem())
+ store.Aux = Types[TINT]
+ s.vars[&memVar] = store
}
if skip&skipCap == 0 {
cap := s.newValue1(ssa.OpSliceCap, Types[TINT], right)
capAddr := s.newValue1I(ssa.OpOffPtr, ptrto(Types[TINT]), 2*s.config.IntSize, left)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, capAddr, cap, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, capAddr, cap, s.mem())
+ store.Aux = Types[TINT]
+ s.vars[&memVar] = store
}
case t.IsInterface():
// itab field doesn't need a write barrier (even though it is a pointer).
itab := s.newValue1(ssa.OpITab, ptrto(Types[TUINT8]), right)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, left, itab, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, left, itab, s.mem())
+ store.Aux = Types[TUINTPTR]
+ s.vars[&memVar] = store
case t.IsStruct():
n := t.NumFields()
for i := 0; i < n; i++ {
func (s *state) storeTypePtrs(t *Type, left, right *ssa.Value) {
switch {
case t.IsPtrShaped():
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, right, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, right, s.mem())
+ store.Aux = t
+ s.vars[&memVar] = store
case t.IsString():
ptr := s.newValue1(ssa.OpStringPtr, ptrto(Types[TUINT8]), right)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store.Aux = ptrto(Types[TUINT8])
+ s.vars[&memVar] = store
case t.IsSlice():
ptr := s.newValue1(ssa.OpSlicePtr, ptrto(Types[TUINT8]), right)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store.Aux = ptrto(Types[TUINT8])
+ s.vars[&memVar] = store
case t.IsInterface():
// itab field is treated as a scalar.
idata := s.newValue1(ssa.OpIData, ptrto(Types[TUINT8]), right)
idataAddr := s.newValue1I(ssa.OpOffPtr, ptrto(ptrto(Types[TUINT8])), s.config.PtrSize, left)
- s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, idataAddr, idata, s.mem())
+ store := s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, idataAddr, idata, s.mem())
+ store.Aux = ptrto(Types[TUINT8])
+ s.vars[&memVar] = store
case t.IsStruct():
n := t.NumFields()
for i := 0; i < n; i++ {
func (s *state) storeTypePtrsWB(t *Type, left, right *ssa.Value) {
switch {
case t.IsPtrShaped():
- s.vars[&memVar] = s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, left, right, s.mem())
+ store := s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, left, right, s.mem())
+ store.Aux = t
+ s.vars[&memVar] = store
case t.IsString():
ptr := s.newValue1(ssa.OpStringPtr, ptrto(Types[TUINT8]), right)
- s.vars[&memVar] = s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store := s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store.Aux = ptrto(Types[TUINT8])
+ s.vars[&memVar] = store
case t.IsSlice():
ptr := s.newValue1(ssa.OpSlicePtr, ptrto(Types[TUINT8]), right)
- s.vars[&memVar] = s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store := s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
+ store.Aux = ptrto(Types[TUINT8])
+ s.vars[&memVar] = store
case t.IsInterface():
// itab field is treated as a scalar.
idata := s.newValue1(ssa.OpIData, ptrto(Types[TUINT8]), right)
idataAddr := s.newValue1I(ssa.OpOffPtr, ptrto(ptrto(Types[TUINT8])), s.config.PtrSize, left)
- s.vars[&memVar] = s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, idataAddr, idata, s.mem())
+ store := s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, idataAddr, idata, s.mem())
+ store.Aux = ptrto(Types[TUINT8])
+ s.vars[&memVar] = store
case t.IsStruct():
n := t.NumFields()
for i := 0; i < n; i++ {
}
} else {
p := s.newValue1(ssa.OpIData, ptrto(n.Type), iface)
- s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, sizeAlignAuxInt(n.Type), addr, p, s.mem())
+ store := s.newValue3I(ssa.OpMove, ssa.TypeMem, sizeAlignAuxInt(n.Type), addr, p, s.mem())
+ store.Aux = n.Type
+ s.vars[&memVar] = store
}
s.vars[&okVar] = s.constBool(true)
s.endBlock()
if tmp == nil {
s.vars[valVar] = s.zeroVal(n.Type)
} else {
- s.vars[&memVar] = s.newValue2I(ssa.OpZero, ssa.TypeMem, sizeAlignAuxInt(n.Type), addr, s.mem())
+ store := s.newValue2I(ssa.OpZero, ssa.TypeMem, sizeAlignAuxInt(n.Type), addr, s.mem())
+ store.Aux = n.Type
+ s.vars[&memVar] = store
}
s.vars[&okVar] = s.constBool(false)
s.endBlock()
import (
"cmd/compile/internal/ssa"
+ "cmd/internal/obj"
"cmd/internal/src"
"fmt"
)
}
return false
}
+
+// HasPointer returns whether t contains heap pointer.
+// This is used for write barrier insertion, so we ignore
+// pointers to go:notinheap types.
+func (t *Type) HasPointer() bool {
+ if t.IsPtr() && t.Elem().NotInHeap() {
+ return false
+ }
+ return haspointers(t)
+}
+
+func (t *Type) Symbol() *obj.LSym {
+ return Linksym(typenamesym(t))
+}
mem)
)
(Store [8] dst (ComplexMake real imag) mem) ->
- (Store [4]
+ (Store [4] {config.fe.TypeFloat32()}
(OffPtr <config.fe.TypeFloat32().PtrTo()> [4] dst)
imag
- (Store [4] dst real mem))
+ (Store [4] {config.fe.TypeFloat32()} dst real mem))
(Load <t> ptr mem) && t.IsComplex() && t.Size() == 16 ->
(ComplexMake
(Load <config.fe.TypeFloat64()> ptr mem)
mem)
)
(Store [16] dst (ComplexMake real imag) mem) ->
- (Store [8]
+ (Store [8] {config.fe.TypeFloat64()}
(OffPtr <config.fe.TypeFloat64().PtrTo()> [8] dst)
imag
- (Store [8] dst real mem))
+ (Store [8] {config.fe.TypeFloat64()} dst real mem))
// string ops
(StringPtr (StringMake ptr _)) -> ptr
(OffPtr <config.fe.TypeInt().PtrTo()> [config.PtrSize] ptr)
mem))
(Store [2*config.PtrSize] dst (StringMake ptr len) mem) ->
- (Store [config.PtrSize]
+ (Store [config.PtrSize] {config.fe.TypeInt()}
(OffPtr <config.fe.TypeInt().PtrTo()> [config.PtrSize] dst)
len
- (Store [config.PtrSize] dst ptr mem))
+ (Store [config.PtrSize] {config.fe.TypeBytePtr()} dst ptr mem))
// slice ops
(SlicePtr (SliceMake ptr _ _ )) -> ptr
(OffPtr <config.fe.TypeInt().PtrTo()> [2*config.PtrSize] ptr)
mem))
(Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem) ->
- (Store [config.PtrSize]
+ (Store [config.PtrSize] {config.fe.TypeInt()}
(OffPtr <config.fe.TypeInt().PtrTo()> [2*config.PtrSize] dst)
cap
- (Store [config.PtrSize]
+ (Store [config.PtrSize] {config.fe.TypeInt()}
(OffPtr <config.fe.TypeInt().PtrTo()> [config.PtrSize] dst)
len
- (Store [config.PtrSize] dst ptr mem)))
+ (Store [config.PtrSize] {config.fe.TypeBytePtr()} dst ptr mem)))
// interface ops
(ITab (IMake itab _)) -> itab
(OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] ptr)
mem))
(Store [2*config.PtrSize] dst (IMake itab data) mem) ->
- (Store [config.PtrSize]
+ (Store [config.PtrSize] {config.fe.TypeBytePtr()}
(OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] dst)
data
- (Store [config.PtrSize] dst itab mem))
+ (Store [config.PtrSize] {config.fe.TypeUintptr()} dst itab mem))
(Load <config.fe.TypeUInt32()> (OffPtr <config.fe.TypeUInt32().PtrTo()> [4] ptr) mem))
(Store [8] dst (Int64Make hi lo) mem) && !config.BigEndian ->
- (Store [4]
+ (Store [4] {hi.Type}
(OffPtr <hi.Type.PtrTo()> [4] dst)
hi
- (Store [4] dst lo mem))
+ (Store [4] {lo.Type} dst lo mem))
(Store [8] dst (Int64Make hi lo) mem) && config.BigEndian ->
- (Store [4]
+ (Store [4] {lo.Type}
(OffPtr <lo.Type.PtrTo()> [4] dst)
lo
- (Store [4] dst hi mem))
+ (Store [4] {hi.Type} dst hi mem))
(Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() ->
(Int64Make
(Store _ (StructMake0) mem) -> mem
(Store dst (StructMake1 <t> f0) mem) ->
- (Store [t.FieldType(0).Size()] (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
+ (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
(Store dst (StructMake2 <t> f0 f1) mem) ->
- (Store [t.FieldType(1).Size()]
+ (Store [t.FieldType(1).Size()] {t.FieldType(1)}
(OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
f1
- (Store [t.FieldType(0).Size()]
+ (Store [t.FieldType(0).Size()] {t.FieldType(0)}
(OffPtr <t.FieldType(0).PtrTo()> [0] dst)
f0 mem))
(Store dst (StructMake3 <t> f0 f1 f2) mem) ->
- (Store [t.FieldType(2).Size()]
+ (Store [t.FieldType(2).Size()] {t.FieldType(2)}
(OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
f2
- (Store [t.FieldType(1).Size()]
+ (Store [t.FieldType(1).Size()] {t.FieldType(1)}
(OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
f1
- (Store [t.FieldType(0).Size()]
+ (Store [t.FieldType(0).Size()] {t.FieldType(0)}
(OffPtr <t.FieldType(0).PtrTo()> [0] dst)
f0 mem)))
(Store dst (StructMake4 <t> f0 f1 f2 f3) mem) ->
- (Store [t.FieldType(3).Size()]
+ (Store [t.FieldType(3).Size()] {t.FieldType(3)}
(OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst)
f3
- (Store [t.FieldType(2).Size()]
+ (Store [t.FieldType(2).Size()] {t.FieldType(2)}
(OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
f2
- (Store [t.FieldType(1).Size()]
+ (Store [t.FieldType(1).Size()] {t.FieldType(1)}
(OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
f1
- (Store [t.FieldType(0).Size()]
+ (Store [t.FieldType(0).Size()] {t.FieldType(0)}
(OffPtr <t.FieldType(0).PtrTo()> [0] dst)
f0 mem))))
// un-SSAable values use mem->mem copies
(Store [size] dst (Load <t> src mem) mem) && !config.fe.CanSSA(t) ->
- (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] dst src mem)
+ (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] {t} dst src mem)
(Store [size] dst (Load <t> src mem) (VarDef {x} mem)) && !config.fe.CanSSA(t) ->
- (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] dst src (VarDef {x} mem))
+ (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] {t} dst src (VarDef {x} mem))
// array ops
(ArraySelect (ArrayMake1 x)) -> x
(ArrayMake1 (Load <t.ElemType()> ptr mem))
(Store _ (ArrayMake0) mem) -> mem
-(Store [size] dst (ArrayMake1 e) mem) -> (Store [size] dst e mem)
+(Store [size] dst (ArrayMake1 e) mem) -> (Store [size] {e.Type} dst e mem)
(ArraySelect [0] (Load ptr mem)) -> (Load ptr mem)
{name: "Invalid"}, // unused value
// Memory operations
- {name: "Load", argLength: 2}, // Load from arg0. arg1=memory
- {name: "Store", argLength: 3, typ: "Mem", aux: "Int64"}, // Store arg1 to arg0. arg2=memory, auxint=size. Returns memory.
- {name: "Move", argLength: 3, typ: "Mem", aux: "SizeAndAlign"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size+alignment. Returns memory.
- {name: "Zero", argLength: 2, typ: "Mem", aux: "SizeAndAlign"}, // arg0=destptr, arg1=mem, auxint=size+alignment. Returns memory.
+ {name: "Load", argLength: 2}, // Load from arg0. arg1=memory
+ {name: "Store", argLength: 3, typ: "Mem", aux: "SymOff", symEffect: "None"}, // Store arg1 to arg0. arg2=memory, auxint=size, aux=type. Returns memory.
+ {name: "Move", argLength: 3, typ: "Mem", aux: "SymSizeAndAlign", symEffect: "None"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size+alignment, aux=type. Returns memory.
+ {name: "Zero", argLength: 2, typ: "Mem", aux: "SymSizeAndAlign", symEffect: "None"}, // arg0=destptr, arg1=mem, auxint=size+alignment, aux=type. Returns memory.
// Memory operations with write barriers.
// Expand to runtime calls. Write barrier will be removed if write on stack.
- {name: "StoreWB", argLength: 3, typ: "Mem", aux: "Int64"}, // Store arg1 to arg0. arg2=memory, auxint=size. Returns memory.
- {name: "MoveWB", argLength: 3, typ: "Mem", aux: "SymSizeAndAlign", symEffect: "None"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size+alignment, aux=symbol-of-type (for typedmemmove). Returns memory.
- {name: "ZeroWB", argLength: 2, typ: "Mem", aux: "SymSizeAndAlign", symEffect: "None"}, // arg0=destptr, arg1=mem, auxint=size+alignment, aux=symbol-of-type. Returns memory.
+ {name: "StoreWB", argLength: 3, typ: "Mem", aux: "SymOff", symEffect: "None"}, // Store arg1 to arg0. arg2=memory, auxint=size, aux=type. Returns memory.
+ {name: "MoveWB", argLength: 3, typ: "Mem", aux: "SymSizeAndAlign", symEffect: "None"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size+alignment, aux=type. Returns memory.
+ {name: "ZeroWB", argLength: 2, typ: "Mem", aux: "SymSizeAndAlign", symEffect: "None"}, // arg0=destptr, arg1=mem, auxint=size+alignment, aux=type. Returns memory.
// Function calls. Arguments to the call have already been written to the stack.
// Return values appear on the stack. The method receiver, if any, is treated
// Sanity check aux, auxint.
if auxint != "" {
switch op.aux {
- case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "Float32", "Float64", "SymOff", "SymValAndOff", "SymInt32", "SizeAndAlign":
+ case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "Float32", "Float64", "SymOff", "SymValAndOff", "SymInt32", "SizeAndAlign", "SymSizeAndAlign":
default:
log.Fatalf("%s: op %s %s can't have auxint", loc, op.name, op.aux)
}
}
if aux != "" {
switch op.aux {
- case "String", "Sym", "SymOff", "SymValAndOff", "SymInt32":
+ case "String", "Sym", "SymOff", "SymValAndOff", "SymInt32", "SymSizeAndAlign":
default:
log.Fatalf("%s: op %s %s can't have aux", loc, op.name, op.aux)
}
generic: true,
},
{
- name: "Store",
- auxType: auxInt64,
- argLen: 3,
- generic: true,
+ name: "Store",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymNone,
+ generic: true,
},
{
- name: "Move",
- auxType: auxSizeAndAlign,
- argLen: 3,
- generic: true,
+ name: "Move",
+ auxType: auxSymSizeAndAlign,
+ argLen: 3,
+ symEffect: SymNone,
+ generic: true,
},
{
- name: "Zero",
- auxType: auxSizeAndAlign,
- argLen: 2,
- generic: true,
+ name: "Zero",
+ auxType: auxSymSizeAndAlign,
+ argLen: 2,
+ symEffect: SymNone,
+ generic: true,
},
{
- name: "StoreWB",
- auxType: auxInt64,
- argLen: 3,
- generic: true,
+ name: "StoreWB",
+ auxType: auxSymOff,
+ argLen: 3,
+ symEffect: SymNone,
+ generic: true,
},
{
name: "MoveWB",
_ = b
// match: (Store [8] dst (ComplexMake real imag) mem)
// cond:
- // result: (Store [4] (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] dst) imag (Store [4] dst real mem))
+ // result: (Store [4] {config.fe.TypeFloat32()} (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] dst) imag (Store [4] {config.fe.TypeFloat32()} dst real mem))
for {
if v.AuxInt != 8 {
break
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = 4
+ v.Aux = config.fe.TypeFloat32()
v0 := b.NewValue0(v.Pos, OpOffPtr, config.fe.TypeFloat32().PtrTo())
v0.AuxInt = 4
v0.AddArg(dst)
v.AddArg(imag)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = 4
+ v1.Aux = config.fe.TypeFloat32()
v1.AddArg(dst)
v1.AddArg(real)
v1.AddArg(mem)
}
// match: (Store [16] dst (ComplexMake real imag) mem)
// cond:
- // result: (Store [8] (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] dst) imag (Store [8] dst real mem))
+ // result: (Store [8] {config.fe.TypeFloat64()} (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] dst) imag (Store [8] {config.fe.TypeFloat64()} dst real mem))
for {
if v.AuxInt != 16 {
break
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = 8
+ v.Aux = config.fe.TypeFloat64()
v0 := b.NewValue0(v.Pos, OpOffPtr, config.fe.TypeFloat64().PtrTo())
v0.AuxInt = 8
v0.AddArg(dst)
v.AddArg(imag)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = 8
+ v1.Aux = config.fe.TypeFloat64()
v1.AddArg(dst)
v1.AddArg(real)
v1.AddArg(mem)
}
// match: (Store [2*config.PtrSize] dst (StringMake ptr len) mem)
// cond:
- // result: (Store [config.PtrSize] (OffPtr <config.fe.TypeInt().PtrTo()> [config.PtrSize] dst) len (Store [config.PtrSize] dst ptr mem))
+ // result: (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr <config.fe.TypeInt().PtrTo()> [config.PtrSize] dst) len (Store [config.PtrSize] {config.fe.TypeBytePtr()} dst ptr mem))
for {
if v.AuxInt != 2*config.PtrSize {
break
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = config.PtrSize
+ v.Aux = config.fe.TypeInt()
v0 := b.NewValue0(v.Pos, OpOffPtr, config.fe.TypeInt().PtrTo())
v0.AuxInt = config.PtrSize
v0.AddArg(dst)
v.AddArg(len)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = config.PtrSize
+ v1.Aux = config.fe.TypeBytePtr()
v1.AddArg(dst)
v1.AddArg(ptr)
v1.AddArg(mem)
}
// match: (Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem)
// cond:
- // result: (Store [config.PtrSize] (OffPtr <config.fe.TypeInt().PtrTo()> [2*config.PtrSize] dst) cap (Store [config.PtrSize] (OffPtr <config.fe.TypeInt().PtrTo()> [config.PtrSize] dst) len (Store [config.PtrSize] dst ptr mem)))
+ // result: (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr <config.fe.TypeInt().PtrTo()> [2*config.PtrSize] dst) cap (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr <config.fe.TypeInt().PtrTo()> [config.PtrSize] dst) len (Store [config.PtrSize] {config.fe.TypeBytePtr()} dst ptr mem)))
for {
if v.AuxInt != 3*config.PtrSize {
break
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = config.PtrSize
+ v.Aux = config.fe.TypeInt()
v0 := b.NewValue0(v.Pos, OpOffPtr, config.fe.TypeInt().PtrTo())
v0.AuxInt = 2 * config.PtrSize
v0.AddArg(dst)
v.AddArg(cap)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = config.PtrSize
+ v1.Aux = config.fe.TypeInt()
v2 := b.NewValue0(v.Pos, OpOffPtr, config.fe.TypeInt().PtrTo())
v2.AuxInt = config.PtrSize
v2.AddArg(dst)
v1.AddArg(len)
v3 := b.NewValue0(v.Pos, OpStore, TypeMem)
v3.AuxInt = config.PtrSize
+ v3.Aux = config.fe.TypeBytePtr()
v3.AddArg(dst)
v3.AddArg(ptr)
v3.AddArg(mem)
}
// match: (Store [2*config.PtrSize] dst (IMake itab data) mem)
// cond:
- // result: (Store [config.PtrSize] (OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] dst) data (Store [config.PtrSize] dst itab mem))
+ // result: (Store [config.PtrSize] {config.fe.TypeBytePtr()} (OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] dst) data (Store [config.PtrSize] {config.fe.TypeUintptr()} dst itab mem))
for {
if v.AuxInt != 2*config.PtrSize {
break
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = config.PtrSize
+ v.Aux = config.fe.TypeBytePtr()
v0 := b.NewValue0(v.Pos, OpOffPtr, config.fe.TypeBytePtr().PtrTo())
v0.AuxInt = config.PtrSize
v0.AddArg(dst)
v.AddArg(data)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = config.PtrSize
+ v1.Aux = config.fe.TypeUintptr()
v1.AddArg(dst)
v1.AddArg(itab)
v1.AddArg(mem)
_ = b
// match: (Store [8] dst (Int64Make hi lo) mem)
// cond: !config.BigEndian
- // result: (Store [4] (OffPtr <hi.Type.PtrTo()> [4] dst) hi (Store [4] dst lo mem))
+ // result: (Store [4] {hi.Type} (OffPtr <hi.Type.PtrTo()> [4] dst) hi (Store [4] {lo.Type} dst lo mem))
for {
if v.AuxInt != 8 {
break
}
v.reset(OpStore)
v.AuxInt = 4
+ v.Aux = hi.Type
v0 := b.NewValue0(v.Pos, OpOffPtr, hi.Type.PtrTo())
v0.AuxInt = 4
v0.AddArg(dst)
v.AddArg(hi)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = 4
+ v1.Aux = lo.Type
v1.AddArg(dst)
v1.AddArg(lo)
v1.AddArg(mem)
}
// match: (Store [8] dst (Int64Make hi lo) mem)
// cond: config.BigEndian
- // result: (Store [4] (OffPtr <lo.Type.PtrTo()> [4] dst) lo (Store [4] dst hi mem))
+ // result: (Store [4] {lo.Type} (OffPtr <lo.Type.PtrTo()> [4] dst) lo (Store [4] {hi.Type} dst hi mem))
for {
if v.AuxInt != 8 {
break
}
v.reset(OpStore)
v.AuxInt = 4
+ v.Aux = lo.Type
v0 := b.NewValue0(v.Pos, OpOffPtr, lo.Type.PtrTo())
v0.AuxInt = 4
v0.AddArg(dst)
v.AddArg(lo)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = 4
+ v1.Aux = hi.Type
v1.AddArg(dst)
v1.AddArg(hi)
v1.AddArg(mem)
}
// match: (Store dst (StructMake1 <t> f0) mem)
// cond:
- // result: (Store [t.FieldType(0).Size()] (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
+ // result: (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
for {
dst := v.Args[0]
v_1 := v.Args[1]
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = t.FieldType(0).Size()
+ v.Aux = t.FieldType(0)
v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
v0.AuxInt = 0
v0.AddArg(dst)
}
// match: (Store dst (StructMake2 <t> f0 f1) mem)
// cond:
- // result: (Store [t.FieldType(1).Size()] (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem))
+ // result: (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem))
for {
dst := v.Args[0]
v_1 := v.Args[1]
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = t.FieldType(1).Size()
+ v.Aux = t.FieldType(1)
v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
v0.AuxInt = t.FieldOff(1)
v0.AddArg(dst)
v.AddArg(f1)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = t.FieldType(0).Size()
+ v1.Aux = t.FieldType(0)
v2 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
v2.AuxInt = 0
v2.AddArg(dst)
}
// match: (Store dst (StructMake3 <t> f0 f1 f2) mem)
// cond:
- // result: (Store [t.FieldType(2).Size()] (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)))
+ // result: (Store [t.FieldType(2).Size()] {t.FieldType(2)} (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)))
for {
dst := v.Args[0]
v_1 := v.Args[1]
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = t.FieldType(2).Size()
+ v.Aux = t.FieldType(2)
v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(2).PtrTo())
v0.AuxInt = t.FieldOff(2)
v0.AddArg(dst)
v.AddArg(f2)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = t.FieldType(1).Size()
+ v1.Aux = t.FieldType(1)
v2 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
v2.AuxInt = t.FieldOff(1)
v2.AddArg(dst)
v1.AddArg(f1)
v3 := b.NewValue0(v.Pos, OpStore, TypeMem)
v3.AuxInt = t.FieldType(0).Size()
+ v3.Aux = t.FieldType(0)
v4 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
v4.AuxInt = 0
v4.AddArg(dst)
}
// match: (Store dst (StructMake4 <t> f0 f1 f2 f3) mem)
// cond:
- // result: (Store [t.FieldType(3).Size()] (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst) f3 (Store [t.FieldType(2).Size()] (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem))))
+ // result: (Store [t.FieldType(3).Size()] {t.FieldType(3)} (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst) f3 (Store [t.FieldType(2).Size()] {t.FieldType(2)} (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem))))
for {
dst := v.Args[0]
v_1 := v.Args[1]
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = t.FieldType(3).Size()
+ v.Aux = t.FieldType(3)
v0 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(3).PtrTo())
v0.AuxInt = t.FieldOff(3)
v0.AddArg(dst)
v.AddArg(f3)
v1 := b.NewValue0(v.Pos, OpStore, TypeMem)
v1.AuxInt = t.FieldType(2).Size()
+ v1.Aux = t.FieldType(2)
v2 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(2).PtrTo())
v2.AuxInt = t.FieldOff(2)
v2.AddArg(dst)
v1.AddArg(f2)
v3 := b.NewValue0(v.Pos, OpStore, TypeMem)
v3.AuxInt = t.FieldType(1).Size()
+ v3.Aux = t.FieldType(1)
v4 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(1).PtrTo())
v4.AuxInt = t.FieldOff(1)
v4.AddArg(dst)
v3.AddArg(f1)
v5 := b.NewValue0(v.Pos, OpStore, TypeMem)
v5.AuxInt = t.FieldType(0).Size()
+ v5.Aux = t.FieldType(0)
v6 := b.NewValue0(v.Pos, OpOffPtr, t.FieldType(0).PtrTo())
v6.AuxInt = 0
v6.AddArg(dst)
}
// match: (Store [size] dst (Load <t> src mem) mem)
// cond: !config.fe.CanSSA(t)
- // result: (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] dst src mem)
+ // result: (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] {t} dst src mem)
for {
size := v.AuxInt
dst := v.Args[0]
}
v.reset(OpMove)
v.AuxInt = MakeSizeAndAlign(size, t.Alignment()).Int64()
+ v.Aux = t
v.AddArg(dst)
v.AddArg(src)
v.AddArg(mem)
}
// match: (Store [size] dst (Load <t> src mem) (VarDef {x} mem))
// cond: !config.fe.CanSSA(t)
- // result: (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] dst src (VarDef {x} mem))
+ // result: (Move [MakeSizeAndAlign(size, t.Alignment()).Int64()] {t} dst src (VarDef {x} mem))
for {
size := v.AuxInt
dst := v.Args[0]
}
v.reset(OpMove)
v.AuxInt = MakeSizeAndAlign(size, t.Alignment()).Int64()
+ v.Aux = t
v.AddArg(dst)
v.AddArg(src)
v0 := b.NewValue0(v.Pos, OpVarDef, TypeMem)
}
// match: (Store [size] dst (ArrayMake1 e) mem)
// cond:
- // result: (Store [size] dst e mem)
+ // result: (Store [size] {e.Type} dst e mem)
for {
size := v.AuxInt
dst := v.Args[0]
mem := v.Args[2]
v.reset(OpStore)
v.AuxInt = size
+ v.Aux = e.Type
v.AddArg(dst)
v.AddArg(e)
v.AddArg(mem)
package ssa
+import "cmd/internal/obj"
+
// TODO: use go/types instead?
// A type interface used to import cmd/internal/gc:Type
NumElem() int64 // # of elements of an array
+ HasPointer() bool // has heap pointer
+
String() string
SimpleString() string // a coarser generic description of T, e.g. T's underlying type
Compare(Type) Cmp // compare types, returning one of CMPlt, CMPeq, CMPgt.
+ Symbol() *obj.LSym // the symbol of the type
}
// Special compiler-only types.
func (t *CompilerType) FieldOff(i int) int64 { panic("not implemented") }
func (t *CompilerType) FieldName(i int) string { panic("not implemented") }
func (t *CompilerType) NumElem() int64 { panic("not implemented") }
+func (t *CompilerType) HasPointer() bool { panic("not implemented") }
+func (t *CompilerType) Symbol() *obj.LSym { panic("not implemented") }
type TupleType struct {
first Type
func (t *TupleType) FieldOff(i int) int64 { panic("not implemented") }
func (t *TupleType) FieldName(i int) string { panic("not implemented") }
func (t *TupleType) NumElem() int64 { panic("not implemented") }
+func (t *TupleType) HasPointer() bool { panic("not implemented") }
+func (t *TupleType) Symbol() *obj.LSym { panic("not implemented") }
// Cmp is a comparison between values a and b.
// -1 if a < b
package ssa
+import "cmd/internal/obj"
+
// Stub implementation used for testing.
type TypeImpl struct {
Size_ int64
func (t *TypeImpl) FieldOff(i int) int64 { panic("not implemented") }
func (t *TypeImpl) FieldName(i int) string { panic("not implemented") }
func (t *TypeImpl) NumElem() int64 { panic("not implemented") }
+func (t *TypeImpl) HasPointer() bool { return t.Ptr }
+func (t *TypeImpl) Symbol() *obj.LSym { panic("not implemented") }
func (t *TypeImpl) Equal(u Type) bool {
x, ok := u.(*TypeImpl)
var val *Value
ptr := w.Args[0]
siz := w.AuxInt
- typ := w.Aux // only non-nil for MoveWB, ZeroWB
+ var typ interface{}
+ if w.Op != OpStoreWB {
+ typ = &ExternSymbol{Typ: f.Config.fe.TypeUintptr(), Sym: w.Aux.(Type).Symbol()}
+ }
pos = w.Pos
var op Op