// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Writes dwarf information to object files.

package obj

import (
	"cmd/internal/dwarf"
	"cmd/internal/objabi"
	"cmd/internal/src"
	"fmt"
	"slices"
	"strings"
	"sync"
)

// Generate a sequence of opcodes that is as short as possible.
// See section 6.2.5
const (
	LINE_BASE   = -4
	LINE_RANGE  = 10
	PC_RANGE    = (255 - OPCODE_BASE) / LINE_RANGE
	OPCODE_BASE = 11
)

// generateDebugLinesSymbol fills the debug lines symbol of a given function.
//
// It's worth noting that this function doesn't generate the full debug_lines
// DWARF section, saving that for the linker. This function just generates the
// state machine part of debug_lines. The full table is generated by the
// linker.  Also, we use the file numbers from the full package (not just the
// function in question) when generating the state machine. We do this so we
// don't have to do a fixup on the indices when writing the full section.
func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
	dctxt := dwCtxt{ctxt}

	// Emit a LNE_set_address extended opcode, so as to establish the
	// starting text address of this function.
	dctxt.AddUint8(lines, 0)
	dwarf.Uleb128put(dctxt, lines, 1+int64(ctxt.Arch.PtrSize))
	dctxt.AddUint8(lines, dwarf.DW_LNE_set_address)
	dctxt.AddAddress(lines, s, 0)

	// Set up the debug_lines state machine to the default values
	// we expect at the start of a new sequence.
	stmt := true
	line := int64(1)
	pc := s.Func().Text.Pc
	var lastpc int64 // last PC written to line table, not last PC in func
	fileIndex := 1
	prologue, wrotePrologue := false, false
	// Walk the progs, generating the DWARF table.
	for p := s.Func().Text; p != nil; p = p.Link {
		prologue = prologue || (p.Pos.Xlogue() == src.PosPrologueEnd)
		// If we're not at a real instruction, keep looping!
		if p.Pos.Line() == 0 || (p.Link != nil && p.Link.Pc == p.Pc) {
			continue
		}
		newStmt := p.Pos.IsStmt() != src.PosNotStmt
		newFileIndex, newLine := ctxt.getFileIndexAndLine(p.Pos)
		newFileIndex++ // 1 indexing for the table

		// Output debug info.
		wrote := false
		if newFileIndex != fileIndex {
			dctxt.AddUint8(lines, dwarf.DW_LNS_set_file)
			dwarf.Uleb128put(dctxt, lines, int64(newFileIndex))
			fileIndex = newFileIndex
			wrote = true
		}
		if prologue && !wrotePrologue {
			dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_set_prologue_end))
			wrotePrologue = true
			wrote = true
		}
		if stmt != newStmt {
			dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_negate_stmt))
			stmt = newStmt
			wrote = true
		}

		if line != int64(newLine) || wrote {
			pcdelta := p.Pc - pc
			lastpc = p.Pc
			putpclcdelta(ctxt, dctxt, lines, uint64(pcdelta), int64(newLine)-line)
			line, pc = int64(newLine), p.Pc
		}
	}

	// Because these symbols will be concatenated together by the
	// linker, we need to reset the state machine that controls the
	// debug symbols. Do this using an end-of-sequence operator.
	//
	// Note: at one point in time, Delve did not support multiple end
	// sequence ops within a compilation unit (bug for this:
	// https://github.com/go-delve/delve/issues/1694), however the bug
	// has since been fixed (Oct 2019).
	//
	// Issue 38192: the DWARF standard specifies that when you issue
	// an end-sequence op, the PC value should be one past the last
	// text address in the translation unit, so apply a delta to the
	// text address before the end sequence op. If this isn't done,
	// GDB will assign a line number of zero the last row in the line
	// table, which we don't want.
	lastlen := uint64(s.Size - (lastpc - s.Func().Text.Pc))
	dctxt.AddUint8(lines, dwarf.DW_LNS_advance_pc)
	dwarf.Uleb128put(dctxt, lines, int64(lastlen))
	dctxt.AddUint8(lines, 0) // start extended opcode
	dwarf.Uleb128put(dctxt, lines, 1)
	dctxt.AddUint8(lines, dwarf.DW_LNE_end_sequence)
}

func putpclcdelta(linkctxt *Link, dctxt dwCtxt, s *LSym, deltaPC uint64, deltaLC int64) {
	// Choose a special opcode that minimizes the number of bytes needed to
	// encode the remaining PC delta and LC delta.
	var opcode int64
	if deltaLC < LINE_BASE {
		if deltaPC >= PC_RANGE {
			opcode = OPCODE_BASE + (LINE_RANGE * PC_RANGE)
		} else {
			opcode = OPCODE_BASE + (LINE_RANGE * int64(deltaPC))
		}
	} else if deltaLC < LINE_BASE+LINE_RANGE {
		if deltaPC >= PC_RANGE {
			opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * PC_RANGE)
			if opcode > 255 {
				opcode -= LINE_RANGE
			}
		} else {
			opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * int64(deltaPC))
		}
	} else {
		if deltaPC <= PC_RANGE {
			opcode = OPCODE_BASE + (LINE_RANGE - 1) + (LINE_RANGE * int64(deltaPC))
			if opcode > 255 {
				opcode = 255
			}
		} else {
			// Use opcode 249 (pc+=23, lc+=5) or 255 (pc+=24, lc+=1).
			//
			// Let x=deltaPC-PC_RANGE.  If we use opcode 255, x will be the remaining
			// deltaPC that we need to encode separately before emitting 255.  If we
			// use opcode 249, we will need to encode x+1.  If x+1 takes one more
			// byte to encode than x, then we use opcode 255.
			//
			// In all other cases x and x+1 take the same number of bytes to encode,
			// so we use opcode 249, which may save us a byte in encoding deltaLC,
			// for similar reasons.
			switch deltaPC - PC_RANGE {
			// PC_RANGE is the largest deltaPC we can encode in one byte, using
			// DW_LNS_const_add_pc.
			//
			// (1<<16)-1 is the largest deltaPC we can encode in three bytes, using
			// DW_LNS_fixed_advance_pc.
			//
			// (1<<(7n))-1 is the largest deltaPC we can encode in n+1 bytes for
			// n=1,3,4,5,..., using DW_LNS_advance_pc.
			case PC_RANGE, (1 << 7) - 1, (1 << 16) - 1, (1 << 21) - 1, (1 << 28) - 1,
				(1 << 35) - 1, (1 << 42) - 1, (1 << 49) - 1, (1 << 56) - 1, (1 << 63) - 1:
				opcode = 255
			default:
				opcode = OPCODE_BASE + LINE_RANGE*PC_RANGE - 1 // 249
			}
		}
	}
	if opcode < OPCODE_BASE || opcode > 255 {
		panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
	}

	// Subtract from deltaPC and deltaLC the amounts that the opcode will add.
	deltaPC -= uint64((opcode - OPCODE_BASE) / LINE_RANGE)
	deltaLC -= (opcode-OPCODE_BASE)%LINE_RANGE + LINE_BASE

	// Encode deltaPC.
	if deltaPC != 0 {
		if deltaPC <= PC_RANGE {
			// Adjust the opcode so that we can use the 1-byte DW_LNS_const_add_pc
			// instruction.
			opcode -= LINE_RANGE * int64(PC_RANGE-deltaPC)
			if opcode < OPCODE_BASE {
				panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
			}
			dctxt.AddUint8(s, dwarf.DW_LNS_const_add_pc)
		} else if (1<<14) <= deltaPC && deltaPC < (1<<16) {
			dctxt.AddUint8(s, dwarf.DW_LNS_fixed_advance_pc)
			dctxt.AddUint16(s, uint16(deltaPC))
		} else {
			dctxt.AddUint8(s, dwarf.DW_LNS_advance_pc)
			dwarf.Uleb128put(dctxt, s, int64(deltaPC))
		}
	}

	// Encode deltaLC.
	if deltaLC != 0 {
		dctxt.AddUint8(s, dwarf.DW_LNS_advance_line)
		dwarf.Sleb128put(dctxt, s, deltaLC)
	}

	// Output the special opcode.
	dctxt.AddUint8(s, uint8(opcode))
}

// implement dwarf.Context
type dwCtxt struct{ *Link }

func (c dwCtxt) PtrSize() int {
	return c.Arch.PtrSize
}
func (c dwCtxt) Size(s dwarf.Sym) int64 {
	return s.(*LSym).Size
}
func (c dwCtxt) AddInt(s dwarf.Sym, size int, i int64) {
	ls := s.(*LSym)
	ls.WriteInt(c.Link, ls.Size, size, i)
}
func (c dwCtxt) AddUint16(s dwarf.Sym, i uint16) {
	c.AddInt(s, 2, int64(i))
}
func (c dwCtxt) AddUint8(s dwarf.Sym, i uint8) {
	b := []byte{i}
	c.AddBytes(s, b)
}
func (c dwCtxt) AddBytes(s dwarf.Sym, b []byte) {
	ls := s.(*LSym)
	ls.WriteBytes(c.Link, ls.Size, b)
}
func (c dwCtxt) AddString(s dwarf.Sym, v string) {
	ls := s.(*LSym)
	ls.WriteString(c.Link, ls.Size, len(v), v)
	ls.WriteInt(c.Link, ls.Size, 1, 0)
}
func (c dwCtxt) AddAddress(s dwarf.Sym, data any, value int64) {
	ls := s.(*LSym)
	size := c.PtrSize()
	if data != nil {
		rsym := data.(*LSym)
		ls.WriteAddr(c.Link, ls.Size, size, rsym, value)
	} else {
		ls.WriteInt(c.Link, ls.Size, size, value)
	}
}
func (c dwCtxt) AddCURelativeAddress(s dwarf.Sym, data any, value int64) {
	ls := s.(*LSym)
	rsym := data.(*LSym)
	ls.WriteCURelativeAddr(c.Link, ls.Size, rsym, value)
}
func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t any, ofs int64) {
	panic("should be used only in the linker")
}
func (c dwCtxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t any, ofs int64) {
	size := 4
	if isDwarf64(c.Link) {
		size = 8
	}

	ls := s.(*LSym)
	rsym := t.(*LSym)
	ls.WriteAddr(c.Link, ls.Size, size, rsym, ofs)
	r := &ls.R[len(ls.R)-1]
	r.Type = objabi.R_DWARFSECREF
}

func (c dwCtxt) CurrentOffset(s dwarf.Sym) int64 {
	ls := s.(*LSym)
	return ls.Size
}

// Here "from" is a symbol corresponding to an inlined or concrete
// function, "to" is the symbol for the corresponding abstract
// function, and "dclIdx" is the index of the symbol of interest with
// respect to the Dcl slice of the original pre-optimization version
// of the inlined function.
func (c dwCtxt) RecordDclReference(from dwarf.Sym, to dwarf.Sym, dclIdx int, inlIndex int) {
	ls := from.(*LSym)
	tls := to.(*LSym)
	ridx := len(ls.R) - 1
	c.Link.DwFixups.ReferenceChildDIE(ls, ridx, tls, dclIdx, inlIndex)
}

func (c dwCtxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
	ls := s.(*LSym)
	c.Link.DwFixups.RegisterChildDIEOffsets(ls, vars, offsets)
}

func (c dwCtxt) Logf(format string, args ...any) {
	c.Link.Logf(format, args...)
}

func (c dwCtxt) AddIndirectTextRef(s dwarf.Sym, t any) {
	ls := s.(*LSym)
	tsym := t.(*LSym)
	// Note the doubling below -- DwTextCount is an estimate and
	// usually a little short due to additional wrapper functions and
	// such; by using c.DwTextCount*2 as the limit we'll ensure that
	// we don't run out of space.
	ls.WriteDwTxtAddrx(c.Link, ls.Size, tsym, c.DwTextCount*2)
}

func isDwarf64(ctxt *Link) bool {
	return ctxt.Headtype == objabi.Haix
}

func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfLocSym, dwarfRangesSym, dwarfAbsFnSym, dwarfDebugLines *LSym) {
	if !s.Type.IsText() {
		ctxt.Diag("dwarfSym of non-TEXT %v", s)
	}
	fn := s.Func()
	if fn.dwarfInfoSym == nil {
		fn.dwarfInfoSym = &LSym{
			Type: objabi.SDWARFFCN,
		}
		if ctxt.Flag_locationlists {
			fn.dwarfLocSym = &LSym{
				Type: objabi.SDWARFLOC,
			}
		}
		fn.dwarfRangesSym = &LSym{
			Type: objabi.SDWARFRANGE,
		}
		fn.dwarfDebugLinesSym = &LSym{
			Type: objabi.SDWARFLINES,
		}
		if s.WasInlined() {
			fn.dwarfAbsFnSym = ctxt.DwFixups.AbsFuncDwarfSym(s)
		}
	}
	return fn.dwarfInfoSym, fn.dwarfLocSym, fn.dwarfRangesSym, fn.dwarfAbsFnSym, fn.dwarfDebugLinesSym
}

// textPos returns the source position of the first instruction (prog)
// of the specified function.
func textPos(fn *LSym) src.XPos {
	if p := fn.Func().Text; p != nil {
		return p.Pos
	}
	return src.NoXPos
}

// populateDWARF fills in the DWARF Debugging Information Entries for
// TEXT symbol 's'. The various DWARF symbols must already have been
// initialized in InitTextSym.
func (ctxt *Link) populateDWARF(curfn Func, s *LSym) {
	myimportpath := ctxt.Pkgpath
	if myimportpath == "" {
		return
	}

	info, loc, ranges, absfunc, lines := ctxt.dwarfSym(s)
	if info.Size != 0 {
		ctxt.Diag("makeFuncDebugEntry double process %v", s)
	}
	var scopes []dwarf.Scope
	var inlcalls dwarf.InlCalls
	if ctxt.DebugInfo != nil {
		scopes, inlcalls = ctxt.DebugInfo(ctxt, s, info, curfn)
	}
	var err error
	dwctxt := dwCtxt{ctxt}
	startPos := ctxt.InnermostPos(textPos(s))
	if !startPos.IsKnown() || startPos.RelLine() != uint(s.Func().StartLine) {
		panic("bad startPos")
	}
	fnstate := &dwarf.FnState{
		Name:          TrimInlineHash(s.Name),
		Info:          info,
		Loc:           loc,
		Ranges:        ranges,
		Absfn:         absfunc,
		StartPC:       s,
		Size:          s.Size,
		StartPos:      startPos,
		External:      !s.Static(),
		Scopes:        scopes,
		InlCalls:      inlcalls,
		UseBASEntries: ctxt.UseBASEntries,
	}
	if absfunc != nil {
		err = dwarf.PutAbstractFunc(dwctxt, fnstate)
		if err != nil {
			ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
		}
		err = dwarf.PutConcreteFunc(dwctxt, fnstate, s.Wrapper(),
			ctxt.DwTextCount)
	} else {
		err = dwarf.PutDefaultFunc(dwctxt, fnstate, s.Wrapper())
	}
	if err != nil {
		ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
	}
	// Fill in the debug lines symbol.
	ctxt.generateDebugLinesSymbol(s, lines)
}

// DwarfIntConst creates a link symbol for an integer constant with the
// given name, type and value.
func (ctxt *Link) DwarfIntConst(name, typename string, val int64) {
	myimportpath := ctxt.Pkgpath
	if myimportpath == "" {
		return
	}
	s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
		s.Type = objabi.SDWARFCONST
		ctxt.Data = append(ctxt.Data, s)
	})
	dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
}

// DwarfGlobal creates a link symbol containing a DWARF entry for
// a global variable.
func (ctxt *Link) DwarfGlobal(typename string, varSym *LSym) {
	myimportpath := ctxt.Pkgpath
	if myimportpath == "" || varSym.Local() {
		return
	}
	varname := varSym.Name
	dieSym := &LSym{
		Type: objabi.SDWARFVAR,
	}
	varSym.NewVarInfo().dwarfInfoSym = dieSym
	ctxt.Data = append(ctxt.Data, dieSym)
	typeSym := ctxt.Lookup(dwarf.InfoPrefix + typename)
	dwarf.PutGlobal(dwCtxt{ctxt}, dieSym, typeSym, varSym, varname)
}

func (ctxt *Link) DwarfAbstractFunc(curfn Func, s *LSym) {
	absfn := ctxt.DwFixups.AbsFuncDwarfSym(s)
	if absfn.Size != 0 {
		ctxt.Diag("internal error: DwarfAbstractFunc double process %v", s)
	}
	if s.Func() == nil {
		s.NewFuncInfo()
	}
	scopes, _ := ctxt.DebugInfo(ctxt, s, absfn, curfn)
	dwctxt := dwCtxt{ctxt}
	fnstate := dwarf.FnState{
		Name:          TrimInlineHash(s.Name),
		Info:          absfn,
		Absfn:         absfn,
		StartPos:      ctxt.InnermostPos(curfn.Pos()),
		External:      !s.Static(),
		Scopes:        scopes,
		UseBASEntries: ctxt.UseBASEntries,
	}
	if err := dwarf.PutAbstractFunc(dwctxt, &fnstate); err != nil {
		ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
	}
}

// This table is designed to aid in the creation of references between
// DWARF subprogram DIEs.
//
// In most cases when one DWARF DIE has to refer to another DWARF DIE,
// the target of the reference has an LSym, which makes it easy to use
// the existing relocation mechanism. For DWARF inlined routine DIEs,
// however, the subprogram DIE has to refer to a child
// parameter/variable DIE of the abstract subprogram. This child DIE
// doesn't have an LSym, and also of interest is the fact that when
// DWARF generation is happening for inlined function F within caller
// G, it's possible that DWARF generation hasn't happened yet for F,
// so there is no way to know the offset of a child DIE within F's
// abstract function. Making matters more complex, each inlined
// instance of F may refer to a subset of the original F's variables
// (depending on what happens with optimization, some vars may be
// eliminated).
//
// The fixup table below helps overcome this hurdle. At the point
// where a parameter/variable reference is made (via a call to
// "ReferenceChildDIE"), a fixup record is generate that records
// the relocation that is targeting that child variable. At a later
// point when the abstract function DIE is emitted, there will be
// a call to "RegisterChildDIEOffsets", at which point the offsets
// needed to apply fixups are captured. Finally, once the parallel
// portion of the compilation is done, fixups can actually be applied
// during the "Finalize" method (this can't be done during the
// parallel portion of the compile due to the possibility of data
// races).
//
// This table is also used to record the "precursor" function node for
// each function that is the target of an inline -- child DIE references
// have to be made with respect to the original pre-optimization
// version of the function (to allow for the fact that each inlined
// body may be optimized differently).
type DwarfFixupTable struct {
	ctxt      *Link
	mu        sync.Mutex
	symtab    map[*LSym]int // maps abstract fn LSYM to index in svec
	svec      []symFixups
	precursor map[*LSym]fnState // maps fn Lsym to precursor Node, absfn sym
}

type symFixups struct {
	fixups   []relFixup
	doffsets []declOffset
	inlIndex int32
	defseen  bool
}

type declOffset struct {
	// Index of variable within DCL list of pre-optimization function
	dclIdx int32
	// Offset of var's child DIE with respect to containing subprogram DIE
	offset int32
}

type relFixup struct {
	refsym *LSym
	relidx int32
	dclidx int32
}

type fnState struct {
	// precursor function
	precursor Func
	// abstract function symbol
	absfn *LSym
}

func NewDwarfFixupTable(ctxt *Link) *DwarfFixupTable {
	return &DwarfFixupTable{
		ctxt:      ctxt,
		symtab:    make(map[*LSym]int),
		precursor: make(map[*LSym]fnState),
	}
}

func (ft *DwarfFixupTable) GetPrecursorFunc(s *LSym) Func {
	if fnstate, found := ft.precursor[s]; found {
		return fnstate.precursor
	}
	return nil
}

func (ft *DwarfFixupTable) SetPrecursorFunc(s *LSym, fn Func) {
	if _, found := ft.precursor[s]; found {
		ft.ctxt.Diag("internal error: DwarfFixupTable.SetPrecursorFunc double call on %v", s)
	}

	// initialize abstract function symbol now. This is done here so
	// as to avoid data races later on during the parallel portion of
	// the back end.
	absfn := ft.ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name+dwarf.AbstractFuncSuffix)
	absfn.Set(AttrDuplicateOK, true)
	absfn.Type = objabi.SDWARFABSFCN
	ft.ctxt.Data = append(ft.ctxt.Data, absfn)

	// In the case of "late" inlining (inlines that happen during
	// wrapper generation as opposed to the main inlining phase) it's
	// possible that we didn't cache the abstract function sym for the
	// text symbol -- do so now if needed. See issue 38068.
	if fn := s.Func(); fn != nil && fn.dwarfAbsFnSym == nil {
		fn.dwarfAbsFnSym = absfn
	}

	ft.precursor[s] = fnState{precursor: fn, absfn: absfn}
}

// Make a note of a child DIE reference: relocation 'ridx' within symbol 's'
// is targeting child 'c' of DIE with symbol 'tgt'.
func (ft *DwarfFixupTable) ReferenceChildDIE(s *LSym, ridx int, tgt *LSym, dclidx int, inlIndex int) {
	// Protect against concurrent access if multiple backend workers
	ft.mu.Lock()
	defer ft.mu.Unlock()

	// Create entry for symbol if not already present.
	idx, found := ft.symtab[tgt]
	if !found {
		ft.svec = append(ft.svec, symFixups{inlIndex: int32(inlIndex)})
		idx = len(ft.svec) - 1
		ft.symtab[tgt] = idx
	}

	// Do we have child DIE offsets available? If so, then apply them,
	// otherwise create a fixup record.
	sf := &ft.svec[idx]
	if len(sf.doffsets) > 0 {
		found := false
		for _, do := range sf.doffsets {
			if do.dclIdx == int32(dclidx) {
				off := do.offset
				s.R[ridx].Add += int64(off)
				found = true
				break
			}
		}
		if !found {
			ft.ctxt.Diag("internal error: DwarfFixupTable.ReferenceChildDIE unable to locate child DIE offset for dclIdx=%d src=%v tgt=%v", dclidx, s, tgt)
		}
	} else {
		sf.fixups = append(sf.fixups, relFixup{s, int32(ridx), int32(dclidx)})
	}
}

// Called once DWARF generation is complete for a given abstract function,
// whose children might have been referenced via a call above. Stores
// the offsets for any child DIEs (vars, params) so that they can be
// consumed later in on DwarfFixupTable.Finalize, which applies any
// outstanding fixups.
func (ft *DwarfFixupTable) RegisterChildDIEOffsets(s *LSym, vars []*dwarf.Var, coffsets []int32) {
	// Length of these two slices should agree
	if len(vars) != len(coffsets) {
		ft.ctxt.Diag("internal error: RegisterChildDIEOffsets vars/offsets length mismatch")
		return
	}

	// Generate the slice of declOffset's based in vars/coffsets
	doffsets := make([]declOffset, len(coffsets))
	for i := range coffsets {
		doffsets[i].dclIdx = vars[i].ChildIndex
		doffsets[i].offset = coffsets[i]
	}

	ft.mu.Lock()
	defer ft.mu.Unlock()

	// Store offsets for this symbol.
	idx, found := ft.symtab[s]
	if !found {
		sf := symFixups{inlIndex: -1, defseen: true, doffsets: doffsets}
		ft.svec = append(ft.svec, sf)
		ft.symtab[s] = len(ft.svec) - 1
	} else {
		sf := &ft.svec[idx]
		sf.doffsets = doffsets
		sf.defseen = true
	}
}

func (ft *DwarfFixupTable) processFixups(slot int, s *LSym) {
	sf := &ft.svec[slot]
	for _, f := range sf.fixups {
		dfound := false
		for _, doffset := range sf.doffsets {
			if doffset.dclIdx == f.dclidx {
				f.refsym.R[f.relidx].Add += int64(doffset.offset)
				dfound = true
				break
			}
		}
		if !dfound {
			ft.ctxt.Diag("internal error: DwarfFixupTable has orphaned fixup on %v targeting %v relidx=%d dclidx=%d", f.refsym, s, f.relidx, f.dclidx)
		}
	}
}

// return the LSym corresponding to the 'abstract subprogram' DWARF
// info entry for a function.
func (ft *DwarfFixupTable) AbsFuncDwarfSym(fnsym *LSym) *LSym {
	// Protect against concurrent access if multiple backend workers
	ft.mu.Lock()
	defer ft.mu.Unlock()

	if fnstate, found := ft.precursor[fnsym]; found {
		return fnstate.absfn
	}
	ft.ctxt.Diag("internal error: AbsFuncDwarfSym requested for %v, not seen during inlining", fnsym)
	return nil
}

// Called after all functions have been compiled; the main job of this
// function is to identify cases where there are outstanding fixups.
// This scenario crops up when we have references to variables of an
// inlined routine, but that routine is defined in some other package.
// This helper walks through and locate these fixups, then invokes a
// helper to create an abstract subprogram DIE for each one.
func (ft *DwarfFixupTable) Finalize(myimportpath string, trace bool) {
	if trace {
		ft.ctxt.Logf("DwarfFixupTable.Finalize invoked for %s\n", myimportpath)
	}

	// Collect up the keys from the precursor map, then sort the
	// resulting list (don't want to rely on map ordering here).
	fns := make([]*LSym, len(ft.precursor))
	idx := 0
	for fn := range ft.precursor {
		fns[idx] = fn
		idx++
	}
	slices.SortFunc(fns, func(a, b *LSym) int {
		return strings.Compare(a.Name, b.Name)
	})

	// Should not be called during parallel portion of compilation.
	if ft.ctxt.InParallel {
		ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize call during parallel backend")
	}

	// Generate any missing abstract functions.
	for _, s := range fns {
		absfn := ft.AbsFuncDwarfSym(s)
		slot, found := ft.symtab[absfn]
		if !found || !ft.svec[slot].defseen {
			ft.ctxt.GenAbstractFunc(s)
		}
	}

	// Apply fixups.
	for _, s := range fns {
		absfn := ft.AbsFuncDwarfSym(s)
		slot, found := ft.symtab[absfn]
		if !found {
			ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize orphan abstract function for %v", s)
		} else {
			ft.processFixups(slot, s)
		}
	}
}
