Skip to content

Commit 538acf1

Browse files
committed
go/ssa: add position info to all Load/Store instructions
Was originally https://codereview.appspot.com/92880043/ by Richard Musiol. Change-Id: If0b22cf962b94ef44edbac28a5e5af4acb950991 Reviewed-on: https://go-review.googlesource.com/2174 Reviewed-by: Robert Griesemer <[email protected]>
1 parent 4f13714 commit 538acf1

File tree

5 files changed

+46
-35
lines changed

5 files changed

+46
-35
lines changed

go/ssa/builder.go

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
347347
if v == nil {
348348
v = fn.lookup(obj, escaping)
349349
}
350-
return &address{addr: v, expr: e}
350+
return &address{addr: v, pos: e.Pos(), expr: e}
351351

352352
case *ast.CompositeLit:
353353
t := deref(fn.Pkg.typeOf(e))
@@ -359,7 +359,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
359359
}
360360
v.Comment = "complit"
361361
b.compLit(fn, v, e, true) // initialize in place
362-
return &address{addr: v, expr: e}
362+
return &address{addr: v, pos: e.Lbrace, expr: e}
363363

364364
case *ast.ParenExpr:
365365
return b.addr(fn, e.X, escaping)
@@ -378,6 +378,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
378378
last := len(sel.Index()) - 1
379379
return &address{
380380
addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel),
381+
pos: e.Sel.Pos(),
381382
expr: e.Sel,
382383
}
383384

@@ -410,10 +411,10 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
410411
}
411412
v.setPos(e.Lbrack)
412413
v.setType(et)
413-
return &address{addr: fn.emit(v), expr: e}
414+
return &address{addr: fn.emit(v), pos: e.Lbrack, expr: e}
414415

415416
case *ast.StarExpr:
416-
return &address{addr: b.expr(fn, e.X), starPos: e.Star, expr: e}
417+
return &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e}
417418
}
418419

419420
panic(fmt.Sprintf("unexpected address expression: %T", e))
@@ -891,7 +892,7 @@ func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallEx
891892
}
892893
iaddr.setType(types.NewPointer(vt))
893894
fn.emit(iaddr)
894-
emitStore(fn, iaddr, arg)
895+
emitStore(fn, iaddr, arg, arg.Pos())
895896
}
896897
s := &Slice{X: a}
897898
s.setType(st)
@@ -1044,17 +1045,19 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero
10441045
switch t := typ.Underlying().(type) {
10451046
case *types.Struct:
10461047
if !isZero && len(e.Elts) != t.NumFields() {
1047-
emitMemClear(fn, addr)
1048+
emitMemClear(fn, addr, e.Lbrace)
10481049
isZero = true
10491050
}
10501051
for i, e := range e.Elts {
10511052
fieldIndex := i
1053+
pos := e.Pos()
10521054
if kv, ok := e.(*ast.KeyValueExpr); ok {
10531055
fname := kv.Key.(*ast.Ident).Name
10541056
for i, n := 0, t.NumFields(); i < n; i++ {
10551057
sf := t.Field(i)
10561058
if sf.Name() == fname {
10571059
fieldIndex = i
1060+
pos = kv.Colon
10581061
e = kv.Value
10591062
break
10601063
}
@@ -1067,7 +1070,7 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero
10671070
}
10681071
faddr.setType(types.NewPointer(sf.Type()))
10691072
fn.emit(faddr)
1070-
b.exprInPlace(fn, &address{addr: faddr, expr: e}, e, isZero)
1073+
b.exprInPlace(fn, &address{addr: faddr, pos: pos, expr: e}, e, isZero)
10711074
}
10721075

10731076
case *types.Array, *types.Slice:
@@ -1086,7 +1089,7 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero
10861089
}
10871090

10881091
if !isZero && int64(len(e.Elts)) != at.Len() {
1089-
emitMemClear(fn, array)
1092+
emitMemClear(fn, array, e.Lbrace)
10901093
isZero = true
10911094
}
10921095

@@ -1108,20 +1111,20 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero
11081111
}
11091112
iaddr.setType(types.NewPointer(at.Elem()))
11101113
fn.emit(iaddr)
1111-
b.exprInPlace(fn, &address{addr: iaddr, expr: e}, e, isZero)
1114+
b.exprInPlace(fn, &address{addr: iaddr, pos: e.Pos(), expr: e}, e, isZero)
11121115
}
11131116
if t != at { // slice
11141117
s := &Slice{X: array}
11151118
s.setPos(e.Lbrace)
11161119
s.setType(typ)
1117-
emitStore(fn, addr, fn.emit(s))
1120+
emitStore(fn, addr, fn.emit(s), e.Lbrace)
11181121
}
11191122

11201123
case *types.Map:
11211124
m := &MakeMap{Reserve: intConst(int64(len(e.Elts)))}
11221125
m.setPos(e.Lbrace)
11231126
m.setType(typ)
1124-
emitStore(fn, addr, fn.emit(m))
1127+
emitStore(fn, addr, fn.emit(m), e.Lbrace)
11251128
for _, e := range e.Elts {
11261129
e := e.(*ast.KeyValueExpr)
11271130
loc := &element{
@@ -1337,7 +1340,7 @@ func (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *
13371340
// In a single-type case, y has that type.
13381341
// In multi-type cases, 'case nil' and default,
13391342
// y has the same type as the interface operand.
1340-
emitStore(fn, fn.addNamedLocal(obj), x)
1343+
emitStore(fn, fn.addNamedLocal(obj), x, obj.Pos())
13411344
}
13421345
fn.targets = &targets{
13431346
tail: fn.targets,
@@ -1588,8 +1591,9 @@ func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) {
15881591
// rangeIndexed emits to fn the header for an integer-indexed loop
15891592
// over array, *array or slice value x.
15901593
// The v result is defined only if tv is non-nil.
1594+
// forPos is the position of the "for" token.
15911595
//
1592-
func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type) (k, v Value, loop, done *BasicBlock) {
1596+
func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
15931597
//
15941598
// length = len(x)
15951599
// index = -1
@@ -1623,7 +1627,7 @@ func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type) (k, v Value
16231627
}
16241628

16251629
index := fn.addLocal(tInt, token.NoPos)
1626-
emitStore(fn, index, intConst(-1))
1630+
emitStore(fn, index, intConst(-1), pos)
16271631

16281632
loop = fn.newBasicBlock("rangeindex.loop")
16291633
emitJump(fn, loop)
@@ -1635,7 +1639,7 @@ func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type) (k, v Value
16351639
Y: vOne,
16361640
}
16371641
incr.setType(tInt)
1638-
emitStore(fn, index, fn.emit(incr))
1642+
emitStore(fn, index, fn.emit(incr), pos)
16391643

16401644
body := fn.newBasicBlock("rangeindex.body")
16411645
done = fn.newBasicBlock("rangeindex.done")
@@ -1814,10 +1818,10 @@ func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {
18141818
var loop, done *BasicBlock
18151819
switch rt := x.Type().Underlying().(type) {
18161820
case *types.Slice, *types.Array, *types.Pointer: // *array
1817-
k, v, loop, done = b.rangeIndexed(fn, x, tv)
1821+
k, v, loop, done = b.rangeIndexed(fn, x, tv, s.For)
18181822

18191823
case *types.Chan:
1820-
k, loop, done = b.rangeChan(fn, x, tk, s.TokPos)
1824+
k, loop, done = b.rangeChan(fn, x, tk, s.For)
18211825

18221826
case *types.Map, *types.Basic: // string
18231827
k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)
@@ -1955,7 +1959,7 @@ start:
19551959
// Function has named result parameters (NRPs).
19561960
// Perform parallel assignment of return operands to NRPs.
19571961
for i, r := range results {
1958-
emitStore(fn, fn.namedResults[i], r)
1962+
emitStore(fn, fn.namedResults[i], r, s.Return)
19591963
}
19601964
}
19611965
// Run function calls deferred in this
@@ -2206,7 +2210,7 @@ func (p *Package) Build() {
22062210
done = init.newBasicBlock("init.done")
22072211
emitIf(init, emitLoad(init, initguard), done, doinit)
22082212
init.currentBlock = doinit
2209-
emitStore(init, initguard, vTrue)
2213+
emitStore(init, initguard, vTrue, token.NoPos)
22102214

22112215
// Call the init() function of each package we import.
22122216
for _, pkg := range p.info.Pkg.Imports() {
@@ -2234,7 +2238,7 @@ func (p *Package) Build() {
22342238
// 1:1 initialization: var x, y = a(), b()
22352239
var lval lvalue
22362240
if v := varinit.Lhs[0]; v.Name() != "_" {
2237-
lval = &address{addr: p.values[v].(*Global)}
2241+
lval = &address{addr: p.values[v].(*Global), pos: v.Pos()}
22382242
} else {
22392243
lval = blank{}
22402244
}
@@ -2246,7 +2250,7 @@ func (p *Package) Build() {
22462250
if v.Name() == "_" {
22472251
continue
22482252
}
2249-
emitStore(init, p.values[v].(*Global), emitExtract(init, tuple, i))
2253+
emitStore(init, p.values[v].(*Global), emitExtract(init, tuple, i), v.Pos())
22502254
}
22512255
}
22522256
}

go/ssa/emit.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,11 @@ func emitConv(f *Function, val Value, typ types.Type) Value {
246246
// emitStore emits to f an instruction to store value val at location
247247
// addr, applying implicit conversions as required by assignability rules.
248248
//
249-
func emitStore(f *Function, addr, val Value) *Store {
249+
func emitStore(f *Function, addr, val Value, pos token.Pos) *Store {
250250
s := &Store{
251251
Addr: addr,
252252
Val: emitConv(f, val, deref(addr.Type())),
253+
pos: pos,
253254
}
254255
f.emit(s)
255256
return s
@@ -430,9 +431,9 @@ func zeroValue(f *Function, t types.Type) Value {
430431
}
431432

432433
// emitMemClear emits to f code to zero the value pointed to by ptr.
433-
func emitMemClear(f *Function, ptr Value) {
434+
func emitMemClear(f *Function, ptr Value, pos token.Pos) {
434435
// TODO(adonovan): define and use a 'memclr' intrinsic for aggregate types.
435-
emitStore(f, ptr, zeroValue(f, deref(ptr.Type())))
436+
emitStore(f, ptr, zeroValue(f, deref(ptr.Type())), pos)
436437
}
437438

438439
// createRecoverBlock emits to f a block of code to return after a

go/ssa/lvalue.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,19 @@ type lvalue interface {
2727

2828
// An address is an lvalue represented by a true pointer.
2929
type address struct {
30-
addr Value
31-
starPos token.Pos // source position, if from explicit *addr
32-
expr ast.Expr // source syntax [debug mode]
30+
addr Value
31+
pos token.Pos // source position
32+
expr ast.Expr // source syntax [debug mode]
3333
}
3434

3535
func (a *address) load(fn *Function) Value {
3636
load := emitLoad(fn, a.addr)
37-
load.pos = a.starPos
37+
load.pos = a.pos
3838
return load
3939
}
4040

4141
func (a *address) store(fn *Function, v Value) {
42-
store := emitStore(fn, a.addr, v)
43-
store.pos = a.starPos
42+
store := emitStore(fn, a.addr, v, a.pos)
4443
if a.expr != nil {
4544
// store.Val is v, converted for assignability.
4645
emitDebugRef(fn, a.expr, store.Val, false)

go/ssa/ssa.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,12 @@ type BinOp struct {
564564
// and a boolean indicating the success of the receive. The
565565
// components of the tuple are accessed using Extract.
566566
//
567-
// Pos() returns the ast.UnaryExpr.OpPos or ast.RangeStmt.TokPos (for
568-
// ranging over a channel), if explicit in the source.
567+
// Pos() returns the ast.UnaryExpr.OpPos, if explicit in the source.
568+
// For receive operations (ARROW) implicit in ranging over a channel,
569+
// Pos() returns the ast.RangeStmt.For.
570+
// For implicit memory loads (STAR), Pos() returns the position of the
571+
// most closely associated source-level construct; the details are not
572+
// specified.
569573
//
570574
// Example printed form:
571575
// t0 = *x
@@ -1162,7 +1166,10 @@ type Send struct {
11621166
// The Store instruction stores Val at address Addr.
11631167
// Stores can be of arbitrary types.
11641168
//
1165-
// Pos() returns the ast.StarExpr.Star, if explicit in the source.
1169+
// Pos() returns the position of the source-level construct most closely
1170+
// associated with the memory store operation.
1171+
// Since implicit memory stores are numerous and varied and depend upon
1172+
// implementation choices, the details are not specified.
11661173
//
11671174
// Example printed form:
11681175
// *x = y

go/ssa/testmain.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,15 @@ func testMainSlice(fn *Function, testfuncs []*Function, slice types.Type) Value
247247
pname := fn.emit(fa)
248248

249249
// Emit: *pname = "testfunc"
250-
emitStore(fn, pname, stringConst(testfunc.Name()))
250+
emitStore(fn, pname, stringConst(testfunc.Name()), token.NoPos)
251251

252252
// Emit: pfunc = &pitem.F
253253
fa = &FieldAddr{X: pitem, Field: 1} // .F
254254
fa.setType(tPtrFunc)
255255
pfunc := fn.emit(fa)
256256

257257
// Emit: *pfunc = testfunc
258-
emitStore(fn, pfunc, testfunc)
258+
emitStore(fn, pfunc, testfunc, token.NoPos)
259259
}
260260

261261
// Emit: slice array[:]

0 commit comments

Comments
 (0)