Skip to content

Commit 1e72bf6

Browse files
committed
cmd/compile: experiment which clobbers all dead pointer fields
The experiment "clobberdead" clobbers all pointer fields that the compiler thinks are dead, just before and after every safepoint. Useful for debugging the generation of live pointer bitmaps. Helped find the following issues: Update #15936 Update #16026 Update #16095 Update #18860 Change-Id: Id1d12f86845e3d93bae903d968b1eac61fc461f9 Reviewed-on: https://go-review.googlesource.com/23924 Run-TryBot: Keith Randall <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent e516227 commit 1e72bf6

File tree

22 files changed

+225
-14
lines changed

22 files changed

+225
-14
lines changed

src/cmd/compile/internal/amd64/ssa.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,20 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
895895
p.To.Type = obj.TYPE_MEM
896896
p.To.Reg = v.Args[0].Reg()
897897
gc.AddAux(&p.To, v)
898+
case ssa.OpClobber:
899+
p := s.Prog(x86.AMOVL)
900+
p.From.Type = obj.TYPE_CONST
901+
p.From.Offset = 0xdeaddead
902+
p.To.Type = obj.TYPE_MEM
903+
p.To.Reg = x86.REG_SP
904+
gc.AddAux(&p.To, v)
905+
p = s.Prog(x86.AMOVL)
906+
p.From.Type = obj.TYPE_CONST
907+
p.From.Offset = 0xdeaddead
908+
p.To.Type = obj.TYPE_MEM
909+
p.To.Reg = x86.REG_SP
910+
gc.AddAux(&p.To, v)
911+
p.To.Offset += 4
898912
default:
899913
v.Fatalf("genValue not implemented: %s", v.LongString())
900914
}

src/cmd/compile/internal/arm/ssa.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
759759
v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
760760
case ssa.OpARMInvertFlags:
761761
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
762+
case ssa.OpClobber:
763+
// TODO: implement for clobberdead experiment. Nop is ok for now.
762764
default:
763765
v.Fatalf("genValue not implemented: %s", v.LongString())
764766
}

src/cmd/compile/internal/arm64/ssa.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
662662
v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
663663
case ssa.OpARM64InvertFlags:
664664
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
665+
case ssa.OpClobber:
666+
// TODO: implement for clobberdead experiment. Nop is ok for now.
665667
default:
666668
v.Fatalf("genValue not implemented: %s", v.LongString())
667669
}

src/cmd/compile/internal/gc/plive.go

Lines changed: 165 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ import (
1818
"cmd/compile/internal/ssa"
1919
"cmd/compile/internal/types"
2020
"cmd/internal/obj"
21+
"cmd/internal/objabi"
22+
"cmd/internal/src"
2123
"crypto/md5"
24+
"crypto/sha1"
2225
"fmt"
26+
"os"
2327
"strings"
2428
)
2529

@@ -121,8 +125,7 @@ type Liveness struct {
121125
// index within the stack maps.
122126
stackMapIndex map[*ssa.Value]int
123127

124-
// An array with a bit vector for each safe point tracking
125-
// live variables, indexed by bb.rpo.
128+
// An array with a bit vector for each safe point tracking live variables.
126129
livevars []bvec
127130

128131
cache progeffectscache
@@ -795,6 +798,165 @@ func livenessepilogue(lv *Liveness) {
795798
}
796799
}
797800

801+
func (lv *Liveness) clobber() {
802+
// The clobberdead experiment inserts code to clobber all the dead variables (locals and args)
803+
// before and after every safepoint. This experiment is useful for debugging the generation
804+
// of live pointer bitmaps.
805+
if objabi.Clobberdead_enabled == 0 {
806+
return
807+
}
808+
var varSize int64
809+
for _, n := range lv.vars {
810+
varSize += n.Type.Size()
811+
}
812+
if len(lv.livevars) > 1000 || varSize > 10000 {
813+
// Be careful to avoid doing too much work.
814+
// Bail if >1000 safepoints or >10000 bytes of variables.
815+
// Otherwise, giant functions make this experiment generate too much code.
816+
return
817+
}
818+
if h := os.Getenv("GOCLOBBERDEADHASH"); h != "" {
819+
// Clobber only functions where the hash of the function name matches a pattern.
820+
// Useful for binary searching for a miscompiled function.
821+
hstr := ""
822+
for _, b := range sha1.Sum([]byte(lv.fn.Func.Nname.Sym.Name)) {
823+
hstr += fmt.Sprintf("%08b", b)
824+
}
825+
if !strings.HasSuffix(hstr, h) {
826+
return
827+
}
828+
fmt.Printf("\t\t\tCLOBBERDEAD %s\n", lv.fn.Func.Nname.Sym.Name)
829+
}
830+
if lv.f.Name == "forkAndExecInChild" {
831+
// forkAndExecInChild calls vfork (on linux/amd64, anyway).
832+
// The code we add here clobbers parts of the stack in the child.
833+
// When the parent resumes, it is using the same stack frame. But the
834+
// child has clobbered stack variables that the parent needs. Boom!
835+
// In particular, the sys argument gets clobbered.
836+
// Note to self: GOCLOBBERDEADHASH=011100101110
837+
return
838+
}
839+
840+
var oldSched []*ssa.Value
841+
for _, b := range lv.f.Blocks {
842+
// Copy block's values to a temporary.
843+
oldSched = append(oldSched[:0], b.Values...)
844+
b.Values = b.Values[:0]
845+
846+
// Clobber all dead variables at entry.
847+
if b == lv.f.Entry {
848+
for len(oldSched) > 0 && len(oldSched[0].Args) == 0 {
849+
// Skip argless ops. We need to skip at least
850+
// the lowered ClosurePtr op, because it
851+
// really wants to be first. This will also
852+
// skip ops like InitMem and SP, which are ok.
853+
b.Values = append(b.Values, oldSched[0])
854+
oldSched = oldSched[1:]
855+
}
856+
clobber(lv, b, lv.livevars[0])
857+
}
858+
859+
// Copy values into schedule, adding clobbering around safepoints.
860+
for _, v := range oldSched {
861+
if !issafepoint(v) {
862+
b.Values = append(b.Values, v)
863+
continue
864+
}
865+
before := true
866+
if v.Op.IsCall() && v.Aux != nil && v.Aux.(*obj.LSym) == typedmemmove {
867+
// Can't put clobber code before the call to typedmemmove.
868+
// The variable to-be-copied is marked as dead
869+
// at the callsite. That is ok, though, as typedmemmove
870+
// is marked as nosplit, and the first thing it does
871+
// is to call memmove (also nosplit), after which
872+
// the source value is dead.
873+
// See issue 16026.
874+
before = false
875+
}
876+
if before {
877+
clobber(lv, b, lv.livevars[lv.stackMapIndex[v]])
878+
}
879+
b.Values = append(b.Values, v)
880+
clobber(lv, b, lv.livevars[lv.stackMapIndex[v]])
881+
}
882+
}
883+
}
884+
885+
// clobber generates code to clobber all dead variables (those not marked in live).
886+
// Clobbering instructions are added to the end of b.Values.
887+
func clobber(lv *Liveness, b *ssa.Block, live bvec) {
888+
for i, n := range lv.vars {
889+
if !live.Get(int32(i)) {
890+
clobberVar(b, n)
891+
}
892+
}
893+
}
894+
895+
// clobberVar generates code to trash the pointers in v.
896+
// Clobbering instructions are added to the end of b.Values.
897+
func clobberVar(b *ssa.Block, v *Node) {
898+
clobberWalk(b, v, 0, v.Type)
899+
}
900+
901+
// b = block to which we append instructions
902+
// v = variable
903+
// offset = offset of (sub-portion of) variable to clobber (in bytes)
904+
// t = type of sub-portion of v.
905+
func clobberWalk(b *ssa.Block, v *Node, offset int64, t *types.Type) {
906+
if !types.Haspointers(t) {
907+
return
908+
}
909+
switch t.Etype {
910+
case TPTR32,
911+
TPTR64,
912+
TUNSAFEPTR,
913+
TFUNC,
914+
TCHAN,
915+
TMAP:
916+
clobberPtr(b, v, offset)
917+
918+
case TSTRING:
919+
// struct { byte *str; int len; }
920+
clobberPtr(b, v, offset)
921+
922+
case TINTER:
923+
// struct { Itab *tab; void *data; }
924+
// or, when isnilinter(t)==true:
925+
// struct { Type *type; void *data; }
926+
clobberPtr(b, v, offset)
927+
clobberPtr(b, v, offset+int64(Widthptr))
928+
929+
case TSLICE:
930+
// struct { byte *array; int len; int cap; }
931+
clobberPtr(b, v, offset)
932+
933+
case TARRAY:
934+
for i := int64(0); i < t.NumElem(); i++ {
935+
clobberWalk(b, v, offset+i*t.Elem().Size(), t.Elem())
936+
}
937+
938+
case TSTRUCT:
939+
for _, t1 := range t.Fields().Slice() {
940+
clobberWalk(b, v, offset+t1.Offset, t1.Type)
941+
}
942+
943+
default:
944+
Fatalf("clobberWalk: unexpected type, %v", t)
945+
}
946+
}
947+
948+
// clobberPtr generates a clobber of the pointer at offset offset in v.
949+
// The clobber instruction is added at the end of b.
950+
func clobberPtr(b *ssa.Block, v *Node, offset int64) {
951+
var aux interface{}
952+
if v.Class == PAUTO {
953+
aux = &ssa.AutoSymbol{Node: v}
954+
} else {
955+
aux = &ssa.ArgSymbol{Node: v}
956+
}
957+
b.NewValue0IA(src.NoXPos, ssa.OpClobber, ssa.TypeVoid, offset, aux)
958+
}
959+
798960
func (lv *Liveness) avarinitanyall(b *ssa.Block, any, all bvec) {
799961
if len(b.Preds) == 0 {
800962
any.Clear()
@@ -1154,6 +1316,7 @@ func liveness(e *ssafn, f *ssa.Func) map[*ssa.Value]int {
11541316
livenesssolve(lv)
11551317
livenessepilogue(lv)
11561318
livenesscompact(lv)
1319+
lv.clobber()
11571320
if debuglive >= 2 {
11581321
livenessprintdebug(lv)
11591322
}

src/cmd/compile/internal/mips/ssa.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
754754
case ssa.OpMIPSLoweredGetClosurePtr:
755755
// Closure pointer is R22 (mips.REGCTXT).
756756
gc.CheckLoweredGetClosurePtr(v)
757+
case ssa.OpClobber:
758+
// TODO: implement for clobberdead experiment. Nop is ok for now.
757759
default:
758760
v.Fatalf("genValue not implemented: %s", v.LongString())
759761
}

src/cmd/compile/internal/mips64/ssa.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
519519
case ssa.OpMIPS64LoweredGetClosurePtr:
520520
// Closure pointer is R22 (mips.REGCTXT).
521521
gc.CheckLoweredGetClosurePtr(v)
522+
case ssa.OpClobber:
523+
// TODO: implement for clobberdead experiment. Nop is ok for now.
522524
default:
523525
v.Fatalf("genValue not implemented: %s", v.LongString())
524526
}

src/cmd/compile/internal/ppc64/ssa.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
11321132
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
11331133
case ssa.OpPPC64FlagEQ, ssa.OpPPC64FlagLT, ssa.OpPPC64FlagGT:
11341134
v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
1135-
1135+
case ssa.OpClobber:
1136+
// TODO: implement for clobberdead experiment. Nop is ok for now.
11361137
default:
11371138
v.Fatalf("genValue not implemented: %s", v.LongString())
11381139
}

src/cmd/compile/internal/s390x/ssa.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
732732
bne := s.Prog(s390x.ABNE)
733733
bne.To.Type = obj.TYPE_BRANCH
734734
gc.Patch(bne, cs)
735+
case ssa.OpClobber:
736+
// TODO: implement for clobberdead experiment. Nop is ok for now.
735737
default:
736738
v.Fatalf("genValue not implemented: %s", v.LongString())
737739
}

src/cmd/compile/internal/ssa/gen/386Ops.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ func init() {
389389
faultOnNilArg0: true,
390390
},
391391

392-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
392+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
393393
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
394394
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
395395

src/cmd/compile/internal/ssa/gen/AMD64Ops.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ func init() {
478478
faultOnNilArg0: true,
479479
},
480480

481-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
481+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
482482
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
483483
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
484484

src/cmd/compile/internal/ssa/gen/ARM64Ops.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ func init() {
318318
{name: "CSELULT0", argLength: 2, reg: gp1flags1, asm: "CSEL"}, // returns arg0 if flags indicates unsigned LT, 0 otherwise, arg1=flags
319319

320320
// function calls
321-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
321+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
322322
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
323323
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
324324

src/cmd/compile/internal/ssa/gen/ARMOps.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ func init() {
377377
{name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"}, // arg0 >> 31 if flags indicates HS, arg0 >> arg1 otherwise, signed shift, arg2=flags
378378

379379
// function calls
380-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
380+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
381381
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
382382
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
383383

src/cmd/compile/internal/ssa/gen/MIPS64Ops.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ func init() {
264264
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
265265

266266
// function calls
267-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
267+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
268268
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
269269
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
270270

src/cmd/compile/internal/ssa/gen/MIPSOps.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func init() {
248248
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
249249

250250
// function calls
251-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
251+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
252252
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
253253
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
254254

src/cmd/compile/internal/ssa/gen/PPC64Ops.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func init() {
309309
// Convert pointer to integer, takes a memory operand for ordering.
310310
{name: "MOVDconvert", argLength: 2, reg: gp11, asm: "MOVD"},
311311

312-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
312+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
313313
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gp | sp, ctxt, 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
314314
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
315315

src/cmd/compile/internal/ssa/gen/S390XOps.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ func init() {
413413

414414
{name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"},
415415

416-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
416+
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
417417
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
418418
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
419419

src/cmd/compile/internal/ssa/gen/genericOps.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ var genericOps = []opData{
314314
// Return values appear on the stack. The method receiver, if any, is treated
315315
// as a phantom first argument.
316316
{name: "ClosureCall", argLength: 3, aux: "Int64", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory.
317-
{name: "StaticCall", argLength: 1, aux: "SymOff", call: true, symEffect: "None"}, // call function aux.(*gc.Sym), arg0=memory. auxint=arg size. Returns memory.
317+
{name: "StaticCall", argLength: 1, aux: "SymOff", call: true, symEffect: "None"}, // call function aux.(*obj.LSym), arg0=memory. auxint=arg size. Returns memory.
318318
{name: "InterCall", argLength: 2, aux: "Int64", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory.
319319

320320
// Conversions: signed extensions, zero (unsigned) extensions, truncations
@@ -464,6 +464,9 @@ var genericOps = []opData{
464464
{name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true iff store happens and new memory.
465465
{name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
466466
{name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
467+
468+
// Clobber experiment op
469+
{name: "Clobber", argLength: 0, typ: "Void", aux: "SymOff", symEffect: "None"}, // write an invalid pointer value to the given pointer slot of a stack variable
467470
}
468471

469472
// kind control successors implicit exit

src/cmd/compile/internal/ssa/opGen.go

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)