// Make a second pass through the progs to compute PC ranges for
// the various inlined calls.
+ start := int64(-1)
curii := -1
- var crange *dwarf.Range
var prevp *obj.Prog
for p := fnsym.Func.Text; p != nil; prevp, p = p, p.Link {
if prevp != nil && p.Pos == prevp.Pos {
ii := posInlIndex(p.Pos)
if ii == curii {
continue
- } else {
- // Close out the current range
- endRange(crange, p)
-
- // Begin new range
- crange = beginRange(inlcalls.Calls, p, ii, imap)
- curii = ii
}
+ // Close out the current range
+ if start != -1 {
+ addRange(inlcalls.Calls, start, p.Pc, curii, imap)
+ }
+ // Begin new range
+ start = p.Pc
+ curii = ii
}
- if crange != nil {
- crange.End = fnsym.Size
+ if start != -1 {
+ addRange(inlcalls.Calls, start, fnsym.Size, curii, imap)
}
// Debugging
return -1
}
-func endRange(crange *dwarf.Range, p *obj.Prog) {
- if crange == nil {
- return
+func addRange(calls []dwarf.InlCall, start, end int64, ii int, imap map[int]int) {
+ if start == -1 {
+ panic("bad range start")
+ }
+ if end == -1 {
+ panic("bad range end")
}
- crange.End = p.Pc
-}
-
-func beginRange(calls []dwarf.InlCall, p *obj.Prog, ii int, imap map[int]int) *dwarf.Range {
if ii == -1 {
- return nil
+ return
}
+ if start == end {
+ return
+ }
+ // Append range to correct inlined call
callIdx, found := imap[ii]
if !found {
- Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, p.Pc)
+ Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, start)
}
call := &calls[callIdx]
-
- // Set up range and append to correct inlined call
- call.Ranges = append(call.Ranges, dwarf.Range{Start: p.Pc, End: -1})
- return &call.Ranges[len(call.Ranges)-1]
+ call.Ranges = append(call.Ranges, dwarf.Range{Start: start, End: end})
}
func dumpInlCall(inlcalls dwarf.InlCalls, idx, ilevel int) {
}
}
+ // inlMarks has an entry for each Prog that implements an inline mark.
+ // It maps from that Prog to the global inlining id of the inlined body
+ // which should unwind to this Prog's location.
+ var inlMarks map[*obj.Prog]int32
+ var inlMarkList []*obj.Prog
+
+ // inlMarksByPos maps from a (column 1) source position to the set of
+ // Progs that are in the set above and have that source position.
+ var inlMarksByPos map[src.XPos][]*obj.Prog
+
// Emit basic blocks
for i, b := range f.Blocks {
s.bstart[b.ID] = s.pp.next
}
case ssa.OpInlMark:
p := thearch.Ginsnop(s.pp)
- pp.curfn.Func.lsym.Func.AddInlMark(p, v.AuxInt32())
- // TODO: if matching line number, merge somehow with previous instruction?
+ if inlMarks == nil {
+ inlMarks = map[*obj.Prog]int32{}
+ inlMarksByPos = map[src.XPos][]*obj.Prog{}
+ }
+ inlMarks[p] = v.AuxInt32()
+ inlMarkList = append(inlMarkList, p)
+ pos := v.Pos.AtColumn1()
+ inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
default:
// let the backend handle it
}
}
+ if inlMarks != nil {
+ // We have some inline marks. Try to find other instructions we're
+ // going to emit anyway, and use those instructions instead of the
+ // inline marks.
+ for p := pp.Text; p != nil; p = p.Link {
+ if p.As == obj.ANOP || p.As == obj.AFUNCDATA || p.As == obj.APCDATA || p.As == obj.ATEXT || p.As == obj.APCALIGN || thearch.LinkArch.Family == sys.Wasm {
+ // Don't use 0-sized instructions as inline marks, because we need
+ // to identify inline mark instructions by pc offset.
+ // (Some of these instructions are sometimes zero-sized, sometimes not.
+ // We must not use anything that even might be zero-sized.)
+ // TODO: are there others?
+ continue
+ }
+ if _, ok := inlMarks[p]; ok {
+ // Don't use inline marks themselves. We don't know
+ // whether they will be zero-sized or not yet.
+ continue
+ }
+ pos := p.Pos.AtColumn1()
+ s := inlMarksByPos[pos]
+ if len(s) == 0 {
+ continue
+ }
+ for _, m := range s {
+ // We found an instruction with the same source position as
+ // some of the inline marks.
+ // Use this instruction instead.
+ pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[m])
+ // Make the inline mark a real nop, so it doesn't generate any code.
+ m.As = obj.ANOP
+ m.Pos = src.NoXPos
+ m.From = obj.Addr{}
+ m.To = obj.Addr{}
+ }
+ delete(inlMarksByPos, pos)
+ }
+ // Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction).
+ for _, p := range inlMarkList {
+ if p.As != obj.ANOP {
+ pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[p])
+ }
+ }
+ }
+
if Ctxt.Flag_locationlists {
e.curfn.Func.DebugInfo = ssa.BuildFuncDebug(Ctxt, f, Debug_locationlist > 1, stackOffset)
bstart := s.bstart