"cmd/compile/internal/reflectdata"
"cmd/compile/internal/ssa"
"cmd/compile/internal/ssagen"
+ "cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/dwarf"
"cmd/internal/obj"
}
}
- decls, dwarfVars := createDwarfVars(fnsym, isODCLFUNC, fn, apdecls)
+ var closureVars map[*ir.Name]int64
+ if fn.Needctxt() {
+ closureVars = make(map[*ir.Name]int64)
+ csiter := typecheck.NewClosureStructIter(fn.ClosureVars)
+ for {
+ n, _, offset := csiter.Next()
+ if n == nil {
+ break
+ }
+ closureVars[n] = offset
+ if n.Heapaddr != nil {
+ closureVars[n.Heapaddr] = offset
+ }
+ }
+ }
+
+ decls, dwarfVars := createDwarfVars(fnsym, isODCLFUNC, fn, apdecls, closureVars)
// For each type referenced by the functions auto vars but not
// already referenced by a dwarf var, attach an R_USETYPE relocation to
// createDwarfVars process fn, returning a list of DWARF variables and the
// Nodes they represent.
-func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var) {
+func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir.Name, closureVars map[*ir.Name]int64) ([]*ir.Name, []*dwarf.Var) {
// Collect a raw list of DWARF vars.
var vars []*dwarf.Var
var decls []*ir.Name
var selected ir.NameSet
if base.Ctxt.Flag_locationlists && base.Ctxt.Flag_optimize && fn.DebugInfo != nil && complexOK {
- decls, vars, selected = createComplexVars(fnsym, fn)
+ decls, vars, selected = createComplexVars(fnsym, fn, closureVars)
} else if fn.ABI == obj.ABIInternal && base.Flag.N != 0 && complexOK {
- decls, vars, selected = createABIVars(fnsym, fn, apDecls)
+ decls, vars, selected = createABIVars(fnsym, fn, apDecls, closureVars)
} else {
- decls, vars, selected = createSimpleVars(fnsym, apDecls)
+ decls, vars, selected = createSimpleVars(fnsym, apDecls, closureVars)
}
if fn.DebugInfo != nil {
// Recover zero sized variables eliminated by the stackframe pass
types.CalcSize(n.Type())
if n.Type().Size() == 0 {
decls = append(decls, n)
- vars = append(vars, createSimpleVar(fnsym, n))
+ vars = append(vars, createSimpleVar(fnsym, n, closureVars))
vars[len(vars)-1].StackOffset = 0
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
}
// Args not of SSA-able type are treated here; they
// are homed on the stack in a single place for the
// entire call.
- vars = append(vars, createSimpleVar(fnsym, n))
+ vars = append(vars, createSimpleVar(fnsym, n, closureVars))
decls = append(decls, n)
continue
}
InlIndex: int32(inlIndex),
ChildIndex: -1,
DictIndex: n.DictIndex,
+ ClosureOffset: closureOffset(n, closureVars),
})
// Record go type of to insure that it gets emitted by the linker.
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
// createSimpleVars creates a DWARF entry for every variable declared in the
// function, claiming that they are permanently on the stack.
-func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
+func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Name, closureVars map[*ir.Name]int64) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
var vars []*dwarf.Var
var decls []*ir.Name
var selected ir.NameSet
}
decls = append(decls, n)
- vars = append(vars, createSimpleVar(fnsym, n))
+ vars = append(vars, createSimpleVar(fnsym, n, closureVars))
selected.Add(n)
}
return decls, vars, selected
}
-func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
+func createSimpleVar(fnsym *obj.LSym, n *ir.Name, closureVars map[*ir.Name]int64) *dwarf.Var {
var tag int
var offs int64
InlIndex: int32(inlIndex),
ChildIndex: -1,
DictIndex: n.DictIndex,
+ ClosureOffset: closureOffset(n, closureVars),
}
}
// hybrid approach in which register-resident input params are
// captured with location lists, and all other vars use the "simple"
// strategy.
-func createABIVars(fnsym *obj.LSym, fn *ir.Func, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
+func createABIVars(fnsym *obj.LSym, fn *ir.Func, apDecls []*ir.Name, closureVars map[*ir.Name]int64) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
// Invoke createComplexVars to generate dwarf vars for input parameters
// that are register-allocated according to the ABI rules.
- decls, vars, selected := createComplexVars(fnsym, fn)
+ decls, vars, selected := createComplexVars(fnsym, fn, closureVars)
// Now fill in the remainder of the variables: input parameters
// that are not register-resident, output parameters, and local
}
decls = append(decls, n)
- vars = append(vars, createSimpleVar(fnsym, n))
+ vars = append(vars, createSimpleVar(fnsym, n, closureVars))
selected.Add(n)
}
// createComplexVars creates recomposed DWARF vars with location lists,
// suitable for describing optimized code.
-func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
+func createComplexVars(fnsym *obj.LSym, fn *ir.Func, closureVars map[*ir.Name]int64) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
debugInfo := fn.DebugInfo.(*ssa.FuncDebug)
// Produce a DWARF variable entry for each user variable.
ssaVars.Add(debugInfo.Slots[slot].N)
}
- if dvar := createComplexVar(fnsym, fn, ssa.VarID(varID)); dvar != nil {
+ if dvar := createComplexVar(fnsym, fn, ssa.VarID(varID), closureVars); dvar != nil {
decls = append(decls, n)
vars = append(vars, dvar)
}
}
// createComplexVar builds a single DWARF variable entry and location list.
-func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var {
+func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID, closureVars map[*ir.Name]int64) *dwarf.Var {
debug := fn.DebugInfo.(*ssa.FuncDebug)
n := debug.Vars[varID]
// variables just give it the first one. It's not used otherwise.
// This won't work well if the first slot hasn't been assigned a stack
// location, but it's not obvious how to do better.
- StackOffset: ssagen.StackOffset(debug.Slots[debug.VarSlots[varID][0]]),
- DeclFile: declpos.RelFilename(),
- DeclLine: declpos.RelLine(),
- DeclCol: declpos.RelCol(),
- InlIndex: int32(inlIndex),
- ChildIndex: -1,
- DictIndex: n.DictIndex,
+ StackOffset: ssagen.StackOffset(debug.Slots[debug.VarSlots[varID][0]]),
+ DeclFile: declpos.RelFilename(),
+ DeclLine: declpos.RelLine(),
+ DeclCol: declpos.RelCol(),
+ InlIndex: int32(inlIndex),
+ ChildIndex: -1,
+ DictIndex: n.DictIndex,
+ ClosureOffset: closureOffset(n, closureVars),
}
list := debug.LocationLists[varID]
if len(list) != 0 {
base.Ctxt.Data = append(base.Ctxt.Data, s)
s.P = []byte(types.LocalPkg.Name)
}
+
+func closureOffset(n *ir.Name, closureVars map[*ir.Name]int64) int64 {
+ return closureVars[n]
+}
{DW_AT_location, DW_FORM_block1},
},
},
+ {
+ DW_TAG_variable,
+ DW_CHILDREN_no,
+ []dwAttrForm{
+ {DW_AT_name, DW_FORM_string},
+ {DW_AT_decl_line, DW_FORM_udata},
+ {DW_AT_type, DW_FORM_ref_addr},
+ {DW_AT_go_closure_offset, DW_FORM_udata},
+ {DW_AT_location, DW_FORM_sec_offset},
+ },
+ },
+ {
+ DW_TAG_variable,
+ DW_CHILDREN_no,
+ []dwAttrForm{
+ {DW_AT_name, DW_FORM_string},
+ {DW_AT_decl_line, DW_FORM_udata},
+ {DW_AT_type, DW_FORM_ref_addr},
+ {DW_AT_go_closure_offset, DW_FORM_udata},
+ {DW_AT_location, DW_FORM_block1},
+ },
+ },
{
DW_TAG_variable,
DW_CHILDREN_no,
{DW_AT_location, DW_FORM_block1},
},
},
+ {
+ DW_TAG_formal_parameter,
+ DW_CHILDREN_no,
+ []dwAttrForm{
+ {DW_AT_name, DW_FORM_string},
+ {DW_AT_variable_parameter, DW_FORM_flag},
+ {DW_AT_decl_line, DW_FORM_udata},
+ {DW_AT_type, DW_FORM_ref_addr},
+ {DW_AT_go_closure_offset, DW_FORM_udata},
+ {DW_AT_location, DW_FORM_sec_offset},
+ },
+ },
+ {
+ DW_TAG_formal_parameter,
+ DW_CHILDREN_no,
+ []dwAttrForm{
+ {DW_AT_name, DW_FORM_string},
+ {DW_AT_variable_parameter, DW_FORM_flag},
+ {DW_AT_decl_line, DW_FORM_udata},
+ {DW_AT_type, DW_FORM_ref_addr},
+ {DW_AT_go_closure_offset, DW_FORM_udata},
+ {DW_AT_location, DW_FORM_block1},
+ },
+ },
{
DW_TAG_formal_parameter,
DW_CHILDREN_no,
return DW_ABRV_PUTVAR_START + 3
}
} else {
- if withLoclist {
- return DW_ABRV_PUTVAR_START + 4
+ if v.ClosureOffset > 0 {
+ if withLoclist {
+ return DW_ABRV_PUTVAR_START + 4
+ } else {
+ return DW_ABRV_PUTVAR_START + 5
+ }
} else {
- return DW_ABRV_PUTVAR_START + 5
+ if withLoclist {
+ return DW_ABRV_PUTVAR_START + 6
+ } else {
+ return DW_ABRV_PUTVAR_START + 7
+ }
}
}
} else {
if concrete {
if withLoclist {
- return DW_ABRV_PUTVAR_START + 6
+ return DW_ABRV_PUTVAR_START + 8
} else {
- return DW_ABRV_PUTVAR_START + 7
+ return DW_ABRV_PUTVAR_START + 9
}
} else {
- if withLoclist {
- return DW_ABRV_PUTVAR_START + 8
+ if v.ClosureOffset > 0 {
+ if withLoclist {
+ return DW_ABRV_PUTVAR_START + 10
+ } else {
+ return DW_ABRV_PUTVAR_START + 11
+ }
} else {
- return DW_ABRV_PUTVAR_START + 9
+ if withLoclist {
+ return DW_ABRV_PUTVAR_START + 12
+ } else {
+ return DW_ABRV_PUTVAR_START + 13
+ }
}
}
}