@@ -68,7 +68,6 @@ func initssaconfig() {
68
68
assertI2I = sysfunc ("assertI2I" )
69
69
assertI2I2 = sysfunc ("assertI2I2" )
70
70
deferproc = sysfunc ("deferproc" )
71
- deferprocStack = sysfunc ("deferprocStack" )
72
71
Deferreturn = sysfunc ("deferreturn" )
73
72
Duffcopy = sysvar ("duffcopy" ) // asm func with special ABI
74
73
Duffzero = sysvar ("duffzero" ) // asm func with special ABI
@@ -865,11 +864,7 @@ func (s *state) stmt(n *Node) {
865
864
}
866
865
}
867
866
case ODEFER :
868
- d := callDefer
869
- if n .Esc == EscNever {
870
- d = callDeferStack
871
- }
872
- s .call (n .Left , d )
867
+ s .call (n .Left , callDefer )
873
868
case OGO :
874
869
s .call (n .Left , callGo )
875
870
@@ -2864,7 +2859,6 @@ type callKind int8
2864
2859
const (
2865
2860
callNormal callKind = iota
2866
2861
callDefer
2867
- callDeferStack
2868
2862
callGo
2869
2863
)
2870
2864
@@ -3805,132 +3799,74 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
3805
3799
rcvr = s .newValue1 (ssa .OpIData , types .Types [TUINTPTR ], i )
3806
3800
}
3807
3801
dowidth (fn .Type )
3808
- stksize := fn .Type .ArgWidth () // includes receiver, args, and results
3802
+ stksize := fn .Type .ArgWidth () // includes receiver
3809
3803
3810
3804
// Run all assignments of temps.
3811
3805
// The temps are introduced to avoid overwriting argument
3812
3806
// slots when arguments themselves require function calls.
3813
3807
s .stmtList (n .List )
3814
3808
3809
+ // Store arguments to stack, including defer/go arguments and receiver for method calls.
3810
+ // These are written in SP-offset order.
3811
+ argStart := Ctxt .FixedFrameSize ()
3812
+ // Defer/go args.
3813
+ if k != callNormal {
3814
+ // Write argsize and closure (args to newproc/deferproc).
3815
+ argsize := s .constInt32 (types .Types [TUINT32 ], int32 (stksize ))
3816
+ addr := s .constOffPtrSP (s .f .Config .Types .UInt32Ptr , argStart )
3817
+ s .store (types .Types [TUINT32 ], addr , argsize )
3818
+ addr = s .constOffPtrSP (s .f .Config .Types .UintptrPtr , argStart + int64 (Widthptr ))
3819
+ s .store (types .Types [TUINTPTR ], addr , closure )
3820
+ stksize += 2 * int64 (Widthptr )
3821
+ argStart += 2 * int64 (Widthptr )
3822
+ }
3823
+
3824
+ // Set receiver (for interface calls).
3825
+ if rcvr != nil {
3826
+ addr := s .constOffPtrSP (s .f .Config .Types .UintptrPtr , argStart )
3827
+ s .store (types .Types [TUINTPTR ], addr , rcvr )
3828
+ }
3829
+
3830
+ // Write args.
3831
+ t := n .Left .Type
3832
+ args := n .Rlist .Slice ()
3833
+ if n .Op == OCALLMETH {
3834
+ f := t .Recv ()
3835
+ s .storeArg (args [0 ], f .Type , argStart + f .Offset )
3836
+ args = args [1 :]
3837
+ }
3838
+ for i , n := range args {
3839
+ f := t .Params ().Field (i )
3840
+ s .storeArg (n , f .Type , argStart + f .Offset )
3841
+ }
3842
+
3843
+ // call target
3815
3844
var call * ssa.Value
3816
- if k == callDeferStack {
3817
- // Make a defer struct d on the stack.
3818
- t := deferstruct (stksize )
3819
- d := tempAt (n .Pos , s .curfn , t )
3820
-
3821
- s .vars [& memVar ] = s .newValue1A (ssa .OpVarDef , types .TypeMem , d , s .mem ())
3822
- addr := s .addr (d , false )
3823
-
3824
- // Must match reflect.go:deferstruct and src/runtime/runtime2.go:_defer.
3825
- // 0: siz
3826
- s .store (types .Types [TUINT32 ],
3827
- s .newValue1I (ssa .OpOffPtr , types .Types [TUINT32 ].PtrTo (), t .FieldOff (0 ), addr ),
3828
- s .constInt32 (types .Types [TUINT32 ], int32 (stksize )))
3829
- // 1: started, set in deferprocStack
3830
- // 2: heap, set in deferprocStack
3831
- // 3: sp, set in deferprocStack
3832
- // 4: pc, set in deferprocStack
3833
- // 5: fn
3834
- s .store (closure .Type ,
3835
- s .newValue1I (ssa .OpOffPtr , closure .Type .PtrTo (), t .FieldOff (5 ), addr ),
3836
- closure )
3837
- // 6: panic, set in deferprocStack
3838
- // 7: link, set in deferprocStack
3839
-
3840
- // Then, store all the arguments of the defer call.
3841
- ft := fn .Type
3842
- off := t .FieldOff (8 )
3843
- args := n .Rlist .Slice ()
3844
-
3845
- // Set receiver (for interface calls). Always a pointer.
3846
- if rcvr != nil {
3847
- p := s .newValue1I (ssa .OpOffPtr , ft .Recv ().Type .PtrTo (), off , addr )
3848
- s .store (types .Types [TUINTPTR ], p , rcvr )
3849
- }
3850
- // Set receiver (for method calls).
3851
- if n .Op == OCALLMETH {
3852
- f := ft .Recv ()
3853
- s .storeArgWithBase (args [0 ], f .Type , addr , off + f .Offset )
3854
- args = args [1 :]
3855
- }
3856
- // Set other args.
3857
- for _ , f := range ft .Params ().Fields ().Slice () {
3858
- s .storeArgWithBase (args [0 ], f .Type , addr , off + f .Offset )
3859
- args = args [1 :]
3860
- }
3861
-
3862
- // Call runtime.deferprocStack with pointer to _defer record.
3863
- arg0 := s .constOffPtrSP (types .Types [TUINTPTR ], Ctxt .FixedFrameSize ())
3864
- s .store (types .Types [TUINTPTR ], arg0 , addr )
3865
- call = s .newValue1A (ssa .OpStaticCall , types .TypeMem , deferprocStack , s .mem ())
3866
- if stksize < int64 (Widthptr ) {
3867
- // We need room for both the call to deferprocStack and the call to
3868
- // the deferred function.
3869
- stksize = int64 (Widthptr )
3870
- }
3871
- call .AuxInt = stksize
3872
- } else {
3873
- // Store arguments to stack, including defer/go arguments and receiver for method calls.
3874
- // These are written in SP-offset order.
3875
- argStart := Ctxt .FixedFrameSize ()
3876
- // Defer/go args.
3877
- if k != callNormal {
3878
- // Write argsize and closure (args to newproc/deferproc).
3879
- argsize := s .constInt32 (types .Types [TUINT32 ], int32 (stksize ))
3880
- addr := s .constOffPtrSP (s .f .Config .Types .UInt32Ptr , argStart )
3881
- s .store (types .Types [TUINT32 ], addr , argsize )
3882
- addr = s .constOffPtrSP (s .f .Config .Types .UintptrPtr , argStart + int64 (Widthptr ))
3883
- s .store (types .Types [TUINTPTR ], addr , closure )
3884
- stksize += 2 * int64 (Widthptr )
3885
- argStart += 2 * int64 (Widthptr )
3886
- }
3887
-
3888
- // Set receiver (for interface calls).
3889
- if rcvr != nil {
3890
- addr := s .constOffPtrSP (s .f .Config .Types .UintptrPtr , argStart )
3891
- s .store (types .Types [TUINTPTR ], addr , rcvr )
3892
- }
3893
-
3894
- // Write args.
3895
- t := n .Left .Type
3896
- args := n .Rlist .Slice ()
3897
- if n .Op == OCALLMETH {
3898
- f := t .Recv ()
3899
- s .storeArg (args [0 ], f .Type , argStart + f .Offset )
3900
- args = args [1 :]
3901
- }
3902
- for i , n := range args {
3903
- f := t .Params ().Field (i )
3904
- s .storeArg (n , f .Type , argStart + f .Offset )
3905
- }
3906
-
3907
- // call target
3908
- switch {
3909
- case k == callDefer :
3910
- call = s .newValue1A (ssa .OpStaticCall , types .TypeMem , deferproc , s .mem ())
3911
- case k == callGo :
3912
- call = s .newValue1A (ssa .OpStaticCall , types .TypeMem , newproc , s .mem ())
3913
- case closure != nil :
3914
- // rawLoad because loading the code pointer from a
3915
- // closure is always safe, but IsSanitizerSafeAddr
3916
- // can't always figure that out currently, and it's
3917
- // critical that we not clobber any arguments already
3918
- // stored onto the stack.
3919
- codeptr = s .rawLoad (types .Types [TUINTPTR ], closure )
3920
- call = s .newValue3 (ssa .OpClosureCall , types .TypeMem , codeptr , closure , s .mem ())
3921
- case codeptr != nil :
3922
- call = s .newValue2 (ssa .OpInterCall , types .TypeMem , codeptr , s .mem ())
3923
- case sym != nil :
3924
- call = s .newValue1A (ssa .OpStaticCall , types .TypeMem , sym .Linksym (), s .mem ())
3925
- default :
3926
- Fatalf ("bad call type %v %v" , n .Op , n )
3927
- }
3928
- call .AuxInt = stksize // Call operations carry the argsize of the callee along with them
3845
+ switch {
3846
+ case k == callDefer :
3847
+ call = s .newValue1A (ssa .OpStaticCall , types .TypeMem , deferproc , s .mem ())
3848
+ case k == callGo :
3849
+ call = s .newValue1A (ssa .OpStaticCall , types .TypeMem , newproc , s .mem ())
3850
+ case closure != nil :
3851
+ // rawLoad because loading the code pointer from a
3852
+ // closure is always safe, but IsSanitizerSafeAddr
3853
+ // can't always figure that out currently, and it's
3854
+ // critical that we not clobber any arguments already
3855
+ // stored onto the stack.
3856
+ codeptr = s .rawLoad (types .Types [TUINTPTR ], closure )
3857
+ call = s .newValue3 (ssa .OpClosureCall , types .TypeMem , codeptr , closure , s .mem ())
3858
+ case codeptr != nil :
3859
+ call = s .newValue2 (ssa .OpInterCall , types .TypeMem , codeptr , s .mem ())
3860
+ case sym != nil :
3861
+ call = s .newValue1A (ssa .OpStaticCall , types .TypeMem , sym .Linksym (), s .mem ())
3862
+ default :
3863
+ Fatalf ("bad call type %v %v" , n .Op , n )
3929
3864
}
3865
+ call .AuxInt = stksize // Call operations carry the argsize of the callee along with them
3930
3866
s .vars [& memVar ] = call
3931
3867
3932
3868
// Finish block for defers
3933
- if k == callDefer || k == callDeferStack {
3869
+ if k == callDefer {
3934
3870
b := s .endBlock ()
3935
3871
b .Kind = ssa .BlockDefer
3936
3872
b .SetControl (call )
@@ -4425,27 +4361,17 @@ func (s *state) storeTypePtrs(t *types.Type, left, right *ssa.Value) {
4425
4361
}
4426
4362
4427
4363
func (s * state ) storeArg (n * Node , t * types.Type , off int64 ) {
4428
- s .storeArgWithBase (n , t , s .sp , off )
4429
- }
4430
-
4431
- func (s * state ) storeArgWithBase (n * Node , t * types.Type , base * ssa.Value , off int64 ) {
4432
4364
pt := types .NewPtr (t )
4433
- var addr * ssa.Value
4434
- if base == s .sp {
4435
- // Use special routine that avoids allocation on duplicate offsets.
4436
- addr = s .constOffPtrSP (pt , off )
4437
- } else {
4438
- addr = s .newValue1I (ssa .OpOffPtr , pt , off , base )
4439
- }
4365
+ sp := s .constOffPtrSP (pt , off )
4440
4366
4441
4367
if ! canSSAType (t ) {
4442
4368
a := s .addr (n , false )
4443
- s .move (t , addr , a )
4369
+ s .move (t , sp , a )
4444
4370
return
4445
4371
}
4446
4372
4447
4373
a := s .expr (n )
4448
- s .storeType (t , addr , a , 0 , false )
4374
+ s .storeType (t , sp , a , 0 , false )
4449
4375
}
4450
4376
4451
4377
// slice computes the slice v[i:j:k] and returns ptr, len, and cap of result.
0 commit comments