From: Cherry Zhang Date: Thu, 9 Feb 2017 14:46:44 +0000 (-0500) Subject: cmd/compile: pass types on SSA Store/Move/Zero ops X-Git-Tag: go1.9beta1~1149 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=211c8c9f1a1d11a6f5c42e85ec78cd06a69fbe0c;p=gostls13.git cmd/compile: pass types on SSA Store/Move/Zero ops For SSA Store/Move/Zero ops, attach the type of the value being stored to the op as the Aux field. This type will be used for write barrier insertion (in a followup CL). Since SSA passes do not accurately propagate types of values (because of type casting), we can't simply use type of the store's arguments for write barrier insertion. Passes "toolstash -cmp" on std. Updates #17583. Change-Id: I051d5e5c482931640d1d7d879b2a6bb91f2e0056 Reviewed-on: https://go-review.googlesource.com/36838 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index afa600f526..e776d3f9f4 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -896,7 +896,9 @@ func (s *state) exit() *ssa.Block { 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. @@ -2129,9 +2131,13 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { 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) } @@ -2154,7 +2160,9 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { 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 @@ -2188,13 +2196,17 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { 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 } } } @@ -2354,10 +2366,14 @@ func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, skip skipMa 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. @@ -2378,7 +2394,9 @@ func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, skip skipMa 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. @@ -2954,7 +2972,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { 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 @@ -2963,9 +2983,13 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { 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) } @@ -3328,7 +3352,9 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*Type, args ...*ssa 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)) @@ -3400,7 +3426,8 @@ func (s *state) insertWBmove(t *Type, left, right *ssa.Value) { } 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 } @@ -3433,7 +3460,9 @@ func (s *state) insertWBstore(t *Type, left, right *ssa.Value, skip skipMask) { 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(): @@ -3442,22 +3471,30 @@ func (s *state) storeTypeScalars(t *Type, left, right *ssa.Value, skip skipMask) } 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++ { @@ -3479,18 +3516,26 @@ func (s *state) storeTypeScalars(t *Type, left, right *ssa.Value, skip skipMask) 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++ { @@ -3515,18 +3560,26 @@ func (s *state) storeTypePtrs(t *Type, left, right *ssa.Value) { 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++ { @@ -4127,7 +4180,9 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { } } 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() @@ -4138,7 +4193,9 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { 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() diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index 3ebe622b61..cde9980d59 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -11,6 +11,7 @@ package gc import ( "cmd/compile/internal/ssa" + "cmd/internal/obj" "cmd/internal/src" "fmt" ) @@ -1279,3 +1280,17 @@ func (t *Type) IsUntyped() bool { } 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)) +} diff --git a/src/cmd/compile/internal/ssa/gen/dec.rules b/src/cmd/compile/internal/ssa/gen/dec.rules index 401fba809e..97f6a11c74 100644 --- a/src/cmd/compile/internal/ssa/gen/dec.rules +++ b/src/cmd/compile/internal/ssa/gen/dec.rules @@ -19,10 +19,10 @@ mem) ) (Store [8] dst (ComplexMake real imag) mem) -> - (Store [4] + (Store [4] {config.fe.TypeFloat32()} (OffPtr [4] dst) imag - (Store [4] dst real mem)) + (Store [4] {config.fe.TypeFloat32()} dst real mem)) (Load ptr mem) && t.IsComplex() && t.Size() == 16 -> (ComplexMake (Load ptr mem) @@ -31,10 +31,10 @@ mem) ) (Store [16] dst (ComplexMake real imag) mem) -> - (Store [8] + (Store [8] {config.fe.TypeFloat64()} (OffPtr [8] dst) imag - (Store [8] dst real mem)) + (Store [8] {config.fe.TypeFloat64()} dst real mem)) // string ops (StringPtr (StringMake ptr _)) -> ptr @@ -47,10 +47,10 @@ (OffPtr [config.PtrSize] ptr) mem)) (Store [2*config.PtrSize] dst (StringMake ptr len) mem) -> - (Store [config.PtrSize] + (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr [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 @@ -67,13 +67,13 @@ (OffPtr [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 [2*config.PtrSize] dst) cap - (Store [config.PtrSize] + (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr [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 @@ -86,7 +86,7 @@ (OffPtr [config.PtrSize] ptr) mem)) (Store [2*config.PtrSize] dst (IMake itab data) mem) -> - (Store [config.PtrSize] + (Store [config.PtrSize] {config.fe.TypeBytePtr()} (OffPtr [config.PtrSize] dst) data - (Store [config.PtrSize] dst itab mem)) + (Store [config.PtrSize] {config.fe.TypeUintptr()} dst itab mem)) diff --git a/src/cmd/compile/internal/ssa/gen/dec64.rules b/src/cmd/compile/internal/ssa/gen/dec64.rules index bfa0beeeb2..47399e35e2 100644 --- a/src/cmd/compile/internal/ssa/gen/dec64.rules +++ b/src/cmd/compile/internal/ssa/gen/dec64.rules @@ -31,16 +31,16 @@ (Load (OffPtr [4] ptr) mem)) (Store [8] dst (Int64Make hi lo) mem) && !config.BigEndian -> - (Store [4] + (Store [4] {hi.Type} (OffPtr [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 [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 diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 73341a52d7..29ff6c1c19 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -795,35 +795,35 @@ (Store _ (StructMake0) mem) -> mem (Store dst (StructMake1 f0) mem) -> - (Store [t.FieldType(0).Size()] (OffPtr [0] dst) f0 mem) + (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem) (Store dst (StructMake2 f0 f1) mem) -> - (Store [t.FieldType(1).Size()] + (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 - (Store [t.FieldType(0).Size()] + (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem)) (Store dst (StructMake3 f0 f1 f2) mem) -> - (Store [t.FieldType(2).Size()] + (Store [t.FieldType(2).Size()] {t.FieldType(2)} (OffPtr [t.FieldOff(2)] dst) f2 - (Store [t.FieldType(1).Size()] + (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 - (Store [t.FieldType(0).Size()] + (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem))) (Store dst (StructMake4 f0 f1 f2 f3) mem) -> - (Store [t.FieldType(3).Size()] + (Store [t.FieldType(3).Size()] {t.FieldType(3)} (OffPtr [t.FieldOff(3)] dst) f3 - (Store [t.FieldType(2).Size()] + (Store [t.FieldType(2).Size()] {t.FieldType(2)} (OffPtr [t.FieldOff(2)] dst) f2 - (Store [t.FieldType(1).Size()] + (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 - (Store [t.FieldType(0).Size()] + (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem)))) @@ -833,9 +833,9 @@ // un-SSAable values use mem->mem copies (Store [size] dst (Load 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 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 @@ -847,7 +847,7 @@ (ArrayMake1 (Load 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) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 400bdce395..892641d9cd 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -286,16 +286,16 @@ var genericOps = []opData{ {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 diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go index c027541eba..fd7b33be12 100644 --- a/src/cmd/compile/internal/ssa/gen/rulegen.go +++ b/src/cmd/compile/internal/ssa/gen/rulegen.go @@ -657,14 +657,14 @@ func parseValue(val string, arch arch, loc string) (op opData, oparch string, ty // 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) } diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 390455c2bb..9abd265f31 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -21557,28 +21557,32 @@ var opcodeTable = [...]opInfo{ 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", diff --git a/src/cmd/compile/internal/ssa/rewritedec.go b/src/cmd/compile/internal/ssa/rewritedec.go index 60c18bdd33..8a113743a4 100644 --- a/src/cmd/compile/internal/ssa/rewritedec.go +++ b/src/cmd/compile/internal/ssa/rewritedec.go @@ -303,7 +303,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { _ = b // match: (Store [8] dst (ComplexMake real imag) mem) // cond: - // result: (Store [4] (OffPtr [4] dst) imag (Store [4] dst real mem)) + // result: (Store [4] {config.fe.TypeFloat32()} (OffPtr [4] dst) imag (Store [4] {config.fe.TypeFloat32()} dst real mem)) for { if v.AuxInt != 8 { break @@ -318,6 +318,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -325,6 +326,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -333,7 +335,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { } // match: (Store [16] dst (ComplexMake real imag) mem) // cond: - // result: (Store [8] (OffPtr [8] dst) imag (Store [8] dst real mem)) + // result: (Store [8] {config.fe.TypeFloat64()} (OffPtr [8] dst) imag (Store [8] {config.fe.TypeFloat64()} dst real mem)) for { if v.AuxInt != 16 { break @@ -348,6 +350,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -355,6 +358,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -363,7 +367,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { } // match: (Store [2*config.PtrSize] dst (StringMake ptr len) mem) // cond: - // result: (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) len (Store [config.PtrSize] dst ptr mem)) + // result: (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr [config.PtrSize] dst) len (Store [config.PtrSize] {config.fe.TypeBytePtr()} dst ptr mem)) for { if v.AuxInt != 2*config.PtrSize { break @@ -378,6 +382,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -385,6 +390,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -393,7 +399,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { } // match: (Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem) // cond: - // result: (Store [config.PtrSize] (OffPtr [2*config.PtrSize] dst) cap (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) len (Store [config.PtrSize] dst ptr mem))) + // result: (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr [2*config.PtrSize] dst) cap (Store [config.PtrSize] {config.fe.TypeInt()} (OffPtr [config.PtrSize] dst) len (Store [config.PtrSize] {config.fe.TypeBytePtr()} dst ptr mem))) for { if v.AuxInt != 3*config.PtrSize { break @@ -409,6 +415,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -416,6 +423,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -423,6 +431,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -432,7 +441,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { } // match: (Store [2*config.PtrSize] dst (IMake itab data) mem) // cond: - // result: (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) data (Store [config.PtrSize] dst itab mem)) + // result: (Store [config.PtrSize] {config.fe.TypeBytePtr()} (OffPtr [config.PtrSize] dst) data (Store [config.PtrSize] {config.fe.TypeUintptr()} dst itab mem)) for { if v.AuxInt != 2*config.PtrSize { break @@ -447,6 +456,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) @@ -454,6 +464,7 @@ func rewriteValuedec_OpStore(v *Value, config *Config) bool { 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) diff --git a/src/cmd/compile/internal/ssa/rewritedec64.go b/src/cmd/compile/internal/ssa/rewritedec64.go index d04676fadb..be1684030d 100644 --- a/src/cmd/compile/internal/ssa/rewritedec64.go +++ b/src/cmd/compile/internal/ssa/rewritedec64.go @@ -2398,7 +2398,7 @@ func rewriteValuedec64_OpStore(v *Value, config *Config) bool { _ = b // match: (Store [8] dst (Int64Make hi lo) mem) // cond: !config.BigEndian - // result: (Store [4] (OffPtr [4] dst) hi (Store [4] dst lo mem)) + // result: (Store [4] {hi.Type} (OffPtr [4] dst) hi (Store [4] {lo.Type} dst lo mem)) for { if v.AuxInt != 8 { break @@ -2416,6 +2416,7 @@ func rewriteValuedec64_OpStore(v *Value, config *Config) bool { } 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) @@ -2423,6 +2424,7 @@ func rewriteValuedec64_OpStore(v *Value, config *Config) bool { 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) @@ -2431,7 +2433,7 @@ func rewriteValuedec64_OpStore(v *Value, config *Config) bool { } // match: (Store [8] dst (Int64Make hi lo) mem) // cond: config.BigEndian - // result: (Store [4] (OffPtr [4] dst) lo (Store [4] dst hi mem)) + // result: (Store [4] {lo.Type} (OffPtr [4] dst) lo (Store [4] {hi.Type} dst hi mem)) for { if v.AuxInt != 8 { break @@ -2449,6 +2451,7 @@ func rewriteValuedec64_OpStore(v *Value, config *Config) bool { } 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) @@ -2456,6 +2459,7 @@ func rewriteValuedec64_OpStore(v *Value, config *Config) bool { 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) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index b998266f2b..172e77783d 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -14748,7 +14748,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } // match: (Store dst (StructMake1 f0) mem) // cond: - // result: (Store [t.FieldType(0).Size()] (OffPtr [0] dst) f0 mem) + // result: (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem) for { dst := v.Args[0] v_1 := v.Args[1] @@ -14760,6 +14760,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14770,7 +14771,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } // match: (Store dst (StructMake2 f0 f1) mem) // cond: - // result: (Store [t.FieldType(1).Size()] (OffPtr [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] (OffPtr [0] dst) f0 mem)) + // result: (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem)) for { dst := v.Args[0] v_1 := v.Args[1] @@ -14783,6 +14784,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14790,6 +14792,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14801,7 +14804,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } // match: (Store dst (StructMake3 f0 f1 f2) mem) // cond: - // result: (Store [t.FieldType(2).Size()] (OffPtr [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] (OffPtr [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] (OffPtr [0] dst) f0 mem))) + // result: (Store [t.FieldType(2).Size()] {t.FieldType(2)} (OffPtr [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem))) for { dst := v.Args[0] v_1 := v.Args[1] @@ -14815,6 +14818,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14822,6 +14826,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14829,6 +14834,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14841,7 +14847,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } // match: (Store dst (StructMake4 f0 f1 f2 f3) mem) // cond: - // result: (Store [t.FieldType(3).Size()] (OffPtr [t.FieldOff(3)] dst) f3 (Store [t.FieldType(2).Size()] (OffPtr [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] (OffPtr [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] (OffPtr [0] dst) f0 mem)))) + // result: (Store [t.FieldType(3).Size()] {t.FieldType(3)} (OffPtr [t.FieldOff(3)] dst) f3 (Store [t.FieldType(2).Size()] {t.FieldType(2)} (OffPtr [t.FieldOff(2)] dst) f2 (Store [t.FieldType(1).Size()] {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 (Store [t.FieldType(0).Size()] {t.FieldType(0)} (OffPtr [0] dst) f0 mem)))) for { dst := v.Args[0] v_1 := v.Args[1] @@ -14856,6 +14862,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14863,6 +14870,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14870,6 +14878,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14877,6 +14886,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { 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) @@ -14890,7 +14900,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } // match: (Store [size] dst (Load 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] @@ -14909,6 +14919,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } v.reset(OpMove) v.AuxInt = MakeSizeAndAlign(size, t.Alignment()).Int64() + v.Aux = t v.AddArg(dst) v.AddArg(src) v.AddArg(mem) @@ -14916,7 +14927,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } // match: (Store [size] dst (Load 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] @@ -14940,6 +14951,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } 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) @@ -14964,7 +14976,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { } // 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] @@ -14976,6 +14988,7 @@ func rewriteValuegeneric_OpStore(v *Value, config *Config) bool { mem := v.Args[2] v.reset(OpStore) v.AuxInt = size + v.Aux = e.Type v.AddArg(dst) v.AddArg(e) v.AddArg(mem) diff --git a/src/cmd/compile/internal/ssa/type.go b/src/cmd/compile/internal/ssa/type.go index 3ebee6a8f1..0936cc5184 100644 --- a/src/cmd/compile/internal/ssa/type.go +++ b/src/cmd/compile/internal/ssa/type.go @@ -4,6 +4,8 @@ package ssa +import "cmd/internal/obj" + // TODO: use go/types instead? // A type interface used to import cmd/internal/gc:Type @@ -39,9 +41,12 @@ type Type interface { 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. @@ -80,6 +85,8 @@ func (t *CompilerType) FieldType(i int) Type { panic("not implemented") } 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 @@ -122,6 +129,8 @@ func (t *TupleType) FieldType(i int) 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 diff --git a/src/cmd/compile/internal/ssa/type_test.go b/src/cmd/compile/internal/ssa/type_test.go index 2f917288de..90958995ce 100644 --- a/src/cmd/compile/internal/ssa/type_test.go +++ b/src/cmd/compile/internal/ssa/type_test.go @@ -4,6 +4,8 @@ package ssa +import "cmd/internal/obj" + // Stub implementation used for testing. type TypeImpl struct { Size_ int64 @@ -50,6 +52,8 @@ func (t *TypeImpl) FieldType(i int) Type { panic("not implemented") } 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) diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 0b82a5ba4c..961cf2b2a8 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -159,7 +159,10 @@ func writebarrier(f *Func) { 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