@@ -17,12 +17,14 @@ package liveness
17
17
import (
18
18
"crypto/md5"
19
19
"fmt"
20
+ "sort"
20
21
"strings"
21
22
22
23
"cmd/compile/internal/base"
23
24
"cmd/compile/internal/bitvec"
24
25
"cmd/compile/internal/ir"
25
26
"cmd/compile/internal/objw"
27
+ "cmd/compile/internal/reflectdata"
26
28
"cmd/compile/internal/ssa"
27
29
"cmd/compile/internal/typebits"
28
30
"cmd/compile/internal/types"
@@ -174,13 +176,13 @@ type progeffectscache struct {
174
176
initialized bool
175
177
}
176
178
177
- // ShouldTrack reports whether the liveness analysis
179
+ // shouldTrack reports whether the liveness analysis
178
180
// should track the variable n.
179
181
// We don't care about variables that have no pointers,
180
182
// nor do we care about non-local variables,
181
183
// nor do we care about empty structs (handled by the pointer check),
182
184
// nor do we care about the fake PAUTOHEAP variables.
183
- func ShouldTrack (n * ir.Name ) bool {
185
+ func shouldTrack (n * ir.Name ) bool {
184
186
return (n .Class == ir .PAUTO && n .Esc () != ir .EscHeap || n .Class == ir .PPARAM || n .Class == ir .PPARAMOUT ) && n .Type ().HasPointers ()
185
187
}
186
188
@@ -189,7 +191,7 @@ func ShouldTrack(n *ir.Name) bool {
189
191
func getvariables (fn * ir.Func ) ([]* ir.Name , map [* ir.Name ]int32 ) {
190
192
var vars []* ir.Name
191
193
for _ , n := range fn .Dcl {
192
- if ShouldTrack (n ) {
194
+ if shouldTrack (n ) {
193
195
vars = append (vars , n )
194
196
}
195
197
}
@@ -1179,9 +1181,54 @@ func Compute(curfn *ir.Func, f *ssa.Func, stkptrsize int64, pp *objw.Progs) Map
1179
1181
p .To .Name = obj .NAME_EXTERN
1180
1182
p .To .Sym = fninfo .GCLocals
1181
1183
1184
+ if x := lv .emitStackObjects (); x != nil {
1185
+ p := pp .Prog (obj .AFUNCDATA )
1186
+ p .From .SetConst (objabi .FUNCDATA_StackObjects )
1187
+ p .To .Type = obj .TYPE_MEM
1188
+ p .To .Name = obj .NAME_EXTERN
1189
+ p .To .Sym = x
1190
+ }
1191
+
1182
1192
return lv .livenessMap
1183
1193
}
1184
1194
1195
+ func (lv * liveness ) emitStackObjects () * obj.LSym {
1196
+ var vars []* ir.Name
1197
+ for _ , n := range lv .fn .Dcl {
1198
+ if shouldTrack (n ) && n .Addrtaken () && n .Esc () != ir .EscHeap {
1199
+ vars = append (vars , n )
1200
+ }
1201
+ }
1202
+ if len (vars ) == 0 {
1203
+ return nil
1204
+ }
1205
+
1206
+ // Sort variables from lowest to highest address.
1207
+ sort .Slice (vars , func (i , j int ) bool { return vars [i ].FrameOffset () < vars [j ].FrameOffset () })
1208
+
1209
+ // Populate the stack object data.
1210
+ // Format must match runtime/stack.go:stackObjectRecord.
1211
+ x := base .Ctxt .Lookup (lv .fn .LSym .Name + ".stkobj" )
1212
+ lv .fn .LSym .Func ().StackObjects = x
1213
+ off := 0
1214
+ off = objw .Uintptr (x , off , uint64 (len (vars )))
1215
+ for _ , v := range vars {
1216
+ // Note: arguments and return values have non-negative Xoffset,
1217
+ // in which case the offset is relative to argp.
1218
+ // Locals have a negative Xoffset, in which case the offset is relative to varp.
1219
+ off = objw .Uintptr (x , off , uint64 (v .FrameOffset ()))
1220
+ off = objw .SymPtr (x , off , reflectdata .TypeLinksym (v .Type ()), 0 )
1221
+ }
1222
+
1223
+ if base .Flag .Live != 0 {
1224
+ for _ , v := range vars {
1225
+ base .WarnfAt (v .Pos (), "stack object %v %v" , v , v .Type ())
1226
+ }
1227
+ }
1228
+
1229
+ return x
1230
+ }
1231
+
1185
1232
// isfat reports whether a variable of type t needs multiple assignments to initialize.
1186
1233
// For example:
1187
1234
//
0 commit comments