ssa: add llvm debug info

This commit is contained in:
Li Jie
2024-09-10 11:04:32 +08:00
parent 4bf5dd15e9
commit 3e5338c902
8 changed files with 595 additions and 3 deletions

View File

@@ -228,6 +228,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
sig = types.NewSignatureType(nil, nil, nil, params, results, false)
}
fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx, f.Origin() != nil)
p.pkg.DIBuilder().DebugFunction(fn, p.goProg.Fset.Position(f.Pos()))
}
if nblk := len(f.Blocks); nblk > 0 {
@@ -249,12 +250,14 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
log.Println("==> FuncBody", name)
}
b := fn.NewBuilder()
b.SetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(f.Pos()))
p.bvals = make(map[ssa.Value]llssa.Expr)
off := make([]int, len(f.Blocks))
for i, block := range f.Blocks {
off[i] = p.compilePhis(b, block)
}
p.blkInfos = blocks.Infos(f.Blocks)
p.debugParams(b, f)
i := 0
for {
block := f.Blocks[i]
@@ -277,6 +280,18 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
return fn, nil, goFunc
}
func (p *context) debugParams(b llssa.Builder, f *ssa.Function) {
for argNo, param := range f.Params {
blk := p.fn.Block(0)
pos := p.goProg.Fset.Position(param.Pos())
v := p.compileValue(b, param)
ty := param.Type()
t := b.Pkg.DIBuilder().DIType(p.prog.Type(ty, llssa.InGo), pos)
div := b.Pkg.DIBuilder().DIVarParam(p.fn, p.goProg.Fset.Position(param.Pos()), param.Name(), t, argNo)
b.Pkg.DIBuilder().DebugValue(v, div, p.fn, pos, blk)
}
}
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doMainInit, doModInit bool) llssa.BasicBlock {
var last int
var pyModInit bool
@@ -454,6 +469,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
}
log.Panicln("unreachable:", iv)
}
if v, ok := iv.(ssa.Instruction); ok {
b.SetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(v.Pos()))
}
switch v := iv.(type) {
case *ssa.Call:
ret = p.call(b, llssa.Call, &v.Call)
@@ -684,11 +702,76 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
ch := p.compileValue(b, v.Chan)
x := p.compileValue(b, v.X)
b.Send(ch, x)
case *ssa.DebugRef:
// object := v.Object()
// variable, ok := object.(*types.Var)
// if !ok {
// // Not a local variable.
// return
// }
// if v.IsAddr {
// // *ssa.Alloc or *ssa.FieldAddr
// return
// }
// fn := v.Parent()
// dbgVar := p.getLocalVariable(b, fn, variable)
// pos := p.goProg.Fset.Position(getPos(v))
// value := p.compileValue(b, v.X)
// b.Pkg.DIBuilder().Debug(value, dbgVar, p.fn, pos, b.Func.Block(v.Block().Index))
default:
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
}
}
type poser interface {
Pos() token.Pos
}
func getPos(v poser) token.Pos {
pos := v.Pos()
if pos.IsValid() {
return pos
}
switch v := v.(type) {
case *ssa.MakeInterface:
return getPos(v.X)
case *ssa.MakeClosure:
return v.Fn.(*ssa.Function).Pos()
case *ssa.Return:
syntax := v.Parent().Syntax()
if syntax != nil {
return syntax.End()
}
return token.NoPos
case *ssa.FieldAddr:
return getPos(v.X)
case *ssa.IndexAddr:
return getPos(v.X)
case *ssa.Slice:
return getPos(v.X)
case *ssa.Store:
return getPos(v.Addr)
case *ssa.Extract:
return getPos(v.Tuple)
default:
fmt.Printf("getPos: unknown instr - %T\n", v)
return token.NoPos
}
}
func (p *context) getLocalVariable(b llssa.Builder, fn *ssa.Function, v *types.Var) llssa.DIVar {
pos := p.fset.Position(v.Pos())
t := b.Prog.Type(v.Type(), llssa.InGo)
vt := b.Pkg.DIBuilder().DIType(t, pos)
for i, param := range fn.Params {
if param.Object().(*types.Var) == v {
return b.DIVarParam(p.fn, pos, v.Name(), vt, i)
}
}
return b.DIVarAuto(p.fn, pos, v.Name(), vt)
}
func (p *context) compileFunction(v *ssa.Function) (goFn llssa.Function, pyFn llssa.PyObjRef, kind int) {
// TODO(xsw) v.Pkg == nil: means auto generated function?
if v.Pkg == p.goPkg || v.Pkg == nil {

View File

@@ -267,6 +267,7 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj
}
sig := fn.Signature
aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, fn.Origin() != nil)
// p.pkg.DIBuilder().DebugFunction(aFn, p.goProg.Fset.Position(fn.Pos()))
}
}
return

View File

@@ -236,7 +236,7 @@ func isNeedRuntimeOrPyInit(pkg *packages.Package) (needRuntime, needPyInit bool)
}
const (
ssaBuildMode = ssa.SanityCheckFunctions | ssa.InstantiateGenerics
ssaBuildMode = ssa.SanityCheckFunctions | ssa.InstantiateGenerics | ssa.GlobalDebug
)
type context struct {
@@ -436,6 +436,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles
}
}
args = append(args, exargs...)
args = append(args, "-gdwarf-5", "-v")
// TODO(xsw): show work
if verbose {
@@ -498,6 +499,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) {
cl.SetDebug(0)
}
check(err)
ret.Finalize()
if needLLFile(ctx.mode) {
pkg.ExportFile += ".ll"
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)

View File

@@ -90,7 +90,7 @@ func genFrom(fileOrPkg string, pkgPath string) string {
initial, err := packages.LoadEx(dedup, prog.TypeSizes, cfg, fileOrPkg)
check(err)
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions|ssa.InstantiateGenerics|ssa.GlobalDebug)
pkg := initial[0]
ssaPkg := pkgs[0]

View File

@@ -17,6 +17,7 @@
package ssa
import (
"go/token"
"go/types"
"log"
"strconv"
@@ -173,6 +174,8 @@ type aFunction struct {
freeVars Expr
base int // base = 1 if hasFreeVars; base = 0 otherwise
hasVArg bool
diFunc DIFunction
}
// Function represents a function or method.
@@ -274,6 +277,10 @@ func (p Function) NewBuilder() Builder {
return &aBuilder{b, nil, p, p.Pkg, prog}
}
func (p Function) NewDIBuilder() *llvm.DIBuilder {
return llvm.NewDIBuilder(p.Pkg.mod)
}
// HasBody reports whether the function has a body.
func (p Function) HasBody() bool {
return len(p.blks) > 0
@@ -324,4 +331,33 @@ func (p Function) SetRecover(blk BasicBlock) {
p.recov = blk
}
func (p Function) scopeMeta(b diBuilder, pos token.Position) DIScopeMeta {
if p.diFunc == nil {
paramTypes := make([]llvm.Metadata, len(p.params))
for i, t := range p.params {
paramTypes[i] = b.DIType(t, pos).ll
}
diFuncType := b.di.CreateSubroutineType(llvm.DISubroutineType{
File: b.DIFile(pos.Filename).ll,
Parameters: paramTypes,
})
p.diFunc = &aDIFunction{
b.di.CreateFunction(
p.Pkg.cu.ll,
llvm.DIFunction{
Type: diFuncType,
Name: p.Name(),
LinkageName: p.Name(),
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
IsDefinition: true,
Optimized: false,
},
),
}
p.impl.SetSubprogram(p.diFunc.ll)
}
return &aDIScopeMeta{p.diFunc.ll}
}
// -----------------------------------------------------------------------------

440
ssa/di.go Normal file
View File

@@ -0,0 +1,440 @@
package ssa
import (
"debug/dwarf"
"fmt"
"go/token"
"go/types"
"path/filepath"
"github.com/goplus/llvm"
)
type aDIBuilder struct {
di *llvm.DIBuilder
prog Program
diTypes map[Type]DIType
}
type diBuilder = *aDIBuilder
func newDIBuilder(prog Program, m llvm.Module) diBuilder {
ctx := m.Context()
m.AddNamedMetadataOperand("llvm.module.flags",
ctx.MDNode([]llvm.Metadata{
llvm.ConstInt(ctx.Int32Type(), 2, false).ConstantAsMetadata(), // Warning on mismatch
ctx.MDString("Debug Info Version"),
llvm.ConstInt(ctx.Int32Type(), 3, false).ConstantAsMetadata(),
}),
)
m.AddNamedMetadataOperand("llvm.module.flags",
ctx.MDNode([]llvm.Metadata{
llvm.ConstInt(ctx.Int32Type(), 7, false).ConstantAsMetadata(), // Max on mismatch
ctx.MDString("Dwarf Version"),
llvm.ConstInt(ctx.Int32Type(), 5, false).ConstantAsMetadata(),
}),
)
return &aDIBuilder{
di: llvm.NewDIBuilder(m),
prog: prog,
diTypes: make(map[*aType]DIType),
}
}
func (b diBuilder) Finalize() {
b.di.Finalize()
b.di.Destroy()
b.di = nil
}
// ----------------------------------------------------------------------------
type aCompilationUnit struct {
ll llvm.Metadata
}
type CompilationUnit = *aCompilationUnit
func (b diBuilder) CreateCompileUnit(filename, dir string) CompilationUnit {
return &aCompilationUnit{ll: b.di.CreateCompileUnit(llvm.DICompileUnit{
Language: llvm.DW_LANG_Go,
File: filename,
Dir: dir,
Producer: "LLGo",
Optimized: true,
RuntimeVersion: 1,
})}
}
// ----------------------------------------------------------------------------
type aDIScopeMeta struct {
ll llvm.Metadata
}
type DIScopeMeta = *aDIScopeMeta
type DIScope interface {
scopeMeta(b diBuilder, pos token.Position) DIScopeMeta
}
// ----------------------------------------------------------------------------
type aDIFile struct {
ll llvm.Metadata
}
type DIFile = *aDIFile
func (b diBuilder) createFile(filename string) DIFile {
dir, file := filepath.Split(filename)
return &aDIFile{ll: b.di.CreateFile(file, dir)}
}
func (f DIFile) scopeMeta(b diBuilder, cu CompilationUnit, pos token.Position) DIScopeMeta {
return &aDIScopeMeta{b.DIFile(pos.Filename).ll}
}
// ----------------------------------------------------------------------------
type aDILexicalBlock struct {
ll llvm.Metadata
}
type DILexicalBlock = *aDILexicalBlock
func (b diBuilder) createLexicalBlock(scope DIScope, pos token.Position) DILexicalBlock {
block := llvm.DILexicalBlock{
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
Column: pos.Column,
}
return &aDILexicalBlock{ll: b.di.CreateLexicalBlock(scope.scopeMeta(b, pos).ll, block)}
}
// ----------------------------------------------------------------------------
type aDIType struct {
ll llvm.Metadata
}
type DIType = *aDIType
func (b diBuilder) createType(ty Type, pos token.Position) DIType {
fmt.Printf("Create type: %T, %v\n", ty.RawType(), ty.RawType())
var typ llvm.Metadata
switch t := ty.RawType().(type) {
case *types.Basic:
if t.Kind() == types.UnsafePointer {
typ = b.di.CreatePointerType(llvm.DIPointerType{
Name: "unsafe.Pointer",
SizeInBits: b.prog.SizeOf(b.prog.rawType(t)) * 8,
AlignInBits: uint32(b.prog.sizes.Alignof(t) * 8),
AddressSpace: 0,
})
return &aDIType{typ}
}
var encoding llvm.DwarfTypeEncoding
if t.Info()&types.IsBoolean != 0 {
encoding = llvm.DW_ATE_boolean
} else if t.Info()&types.IsUnsigned != 0 {
encoding = llvm.DW_ATE_unsigned
} else if t.Info()&types.IsInteger != 0 {
encoding = llvm.DW_ATE_signed
} else if t.Info()&types.IsFloat != 0 {
encoding = llvm.DW_ATE_float
} else if t.Info()&types.IsComplex != 0 {
encoding = llvm.DW_ATE_complex_float
} else if t.Info()&types.IsString != 0 {
typ = b.di.CreateBasicType(llvm.DIBasicType{
Name: "string",
SizeInBits: b.prog.SizeOf(b.prog.rawType(t)) * 8,
Encoding: llvm.DW_ATE_unsigned_char,
})
return &aDIType{typ}
} else {
encoding = llvm.DW_ATE_unsigned
panic("todo: basic type")
}
typ = b.di.CreateBasicType(llvm.DIBasicType{
Name: t.Name(),
SizeInBits: b.prog.SizeOf(b.prog.rawType(t)) * 8,
Encoding: encoding,
})
case *types.Pointer:
return b.createPointerType(b.prog.rawType(t.Elem()), pos)
case *types.Named:
return b.DIType(b.prog.rawType(t.Underlying()), pos)
case *types.Interface:
return b.createBasicType(ty)
case *types.Slice:
return b.createBasicType(ty)
case *types.Struct:
return b.createStructType(ty, pos)
case *types.Signature:
return b.createFuncPtrType(b.prog.rawType(t), pos)
case *types.Tuple:
return b.createBasicType(ty)
case *types.Array:
return b.createBasicType(ty)
default:
panic(fmt.Errorf("can't create debug info of type: %v, %T", ty.RawType(), ty.RawType()))
}
return &aDIType{typ}
}
// ----------------------------------------------------------------------------
type aDIFunction struct {
ll llvm.Metadata
}
type DIFunction = *aDIFunction
func (b diBuilder) CreateFunction(scope DIScope, pos token.Position, name, linkageName string, ty DIType, isLocalToUnit, isDefinition, isOptimized bool) DIFunction {
return &aDIFunction{ll: scope.scopeMeta(b, pos).ll}
}
// ----------------------------------------------------------------------------
type aDIGlobalVariableExpression struct {
ll llvm.Metadata
}
type DIGlobalVariableExpression = *aDIGlobalVariableExpression
func (b diBuilder) CreateGlobalVariableExpression(scope DIScope, pos token.Position, name, linkageName string, ty DIType, isLocalToUnit bool) DIGlobalVariableExpression {
return &aDIGlobalVariableExpression{
ll: b.di.CreateGlobalVariableExpression(
scope.scopeMeta(b, pos).ll,
llvm.DIGlobalVariableExpression{
Name: name,
LinkageName: linkageName,
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
Type: ty.ll,
LocalToUnit: isLocalToUnit,
// TODO(lijie): check the following fields
// Expr: llvm.Metadata{},
// Decl: llvm.Metadata{},
// AlignInBits: 0,
},
),
}
}
// ----------------------------------------------------------------------------
type aDIVar struct {
ll llvm.Metadata
}
type DIVar = *aDIVar
func (b diBuilder) CreateParameterVariable(scope DIScope, pos token.Position, name string, argNo int, ty DIType) DIVar {
return &aDIVar{
ll: b.di.CreateParameterVariable(
scope.scopeMeta(b, pos).ll,
llvm.DIParameterVariable{
Name: name,
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
ArgNo: argNo,
Type: ty.ll,
AlwaysPreserve: true,
},
),
}
}
func (b diBuilder) CreateAutoVariable(scope DIScope, pos token.Position, name string, ty DIType) DIVar {
return &aDIVar{
ll: b.di.CreateAutoVariable(
scope.scopeMeta(b, pos).ll,
llvm.DIAutoVariable{
Name: name,
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
Type: ty.ll,
AlwaysPreserve: true,
},
),
}
}
// ----------------------------------------------------------------------------
func (b diBuilder) createBasicType(t Type) DIType {
return &aDIType{ll: b.di.CreateBasicType(llvm.DIBasicType{
Name: t.RawType().String(),
SizeInBits: b.prog.SizeOf(t) * 8,
Encoding: llvm.DW_ATE_unsigned,
})}
}
func (b diBuilder) createPointerType(ty Type, pos token.Position) DIType {
return &aDIType{ll: b.di.CreatePointerType(llvm.DIPointerType{
Pointee: b.DIType(ty, pos).ll,
SizeInBits: b.prog.SizeOf(ty) * 8,
AlignInBits: uint32(b.prog.sizes.Alignof(ty.RawType())) * 8,
AddressSpace: 0,
})}
}
func (b diBuilder) createStructType(ty Type, pos token.Position) (ret DIType) {
scope := b.DIFile(pos.Filename)
ret = &aDIType{b.di.CreateReplaceableCompositeType(
scope.ll,
llvm.DIReplaceableCompositeType{
Tag: dwarf.TagStructType,
Name: ty.RawType().String(),
},
)}
b.diTypes[ty] = ret
// Create struct type
structType := ty.RawType().(*types.Struct)
fields := make([]llvm.Metadata, structType.NumFields())
for i := 0; i < structType.NumFields(); i++ {
field := structType.Field(i)
fields[i] = b.di.CreateMemberType(
scope.ll,
llvm.DIMemberType{
Name: field.Name(),
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
SizeInBits: b.prog.SizeOf(b.prog.rawType(field.Type())) * 8,
AlignInBits: 8,
OffsetInBits: b.prog.OffsetOf(ty, i) * 8,
Type: b.DIType(b.prog.rawType(field.Type()), pos).ll,
},
)
}
st := b.di.CreateStructType(
scope.ll,
llvm.DIStructType{
Name: ty.RawType().String(),
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
SizeInBits: b.prog.SizeOf(ty) * 8,
AlignInBits: uint32(b.prog.sizes.Alignof(structType) * 8),
Elements: fields,
},
)
ret.ll.ReplaceAllUsesWith(st)
ret.ll = st
return
}
func (b diBuilder) createFuncPtrType(ty Type, pos token.Position) DIType {
sig := ty.RawType().(*types.Signature)
retTy := b.DIType(b.prog.rawType(sig.Results()), pos)
paramTys := make([]DIType, sig.Params().Len())
for i := 0; i < sig.Params().Len(); i++ {
paramTys[i] = b.DIType(b.prog.rawType(sig.Params().At(i).Type()), pos)
}
rt := b.createSubroutineType(b.DIFile(pos.Filename), retTy, paramTys)
return &aDIType{ll: b.di.CreatePointerType(llvm.DIPointerType{
Pointee: rt.ll,
SizeInBits: b.prog.SizeOf(ty) * 8,
AlignInBits: 8,
AddressSpace: 0,
})}
}
// ----------------------------------------------------------------------------
func (b diBuilder) createSubroutineType(file DIFile, retTy DIType, paramTys []DIType) DIType {
params := make([]llvm.Metadata, len(paramTys)+1)
params[0] = retTy.ll
for i, ty := range paramTys {
params[i+1] = ty.ll
}
return &aDIType{ll: b.di.CreateSubroutineType(llvm.DISubroutineType{
File: file.ll,
Parameters: params,
Flags: 0,
})}
}
// ----------------------------------------------------------------------------
func (b diBuilder) Debug(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
loc := llvm.DebugLoc{
Line: uint(pos.Line),
Col: uint(pos.Column),
Scope: scope.scopeMeta(b, pos).ll,
}
b.di.InsertDeclareAtEnd(
v.impl,
dv.ll,
b.di.CreateExpression(nil),
loc,
blk.last,
)
}
func (b diBuilder) DebugValue(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
loc := llvm.DebugLoc{
Line: uint(pos.Line),
Col: uint(pos.Column),
Scope: scope.scopeMeta(b, pos).ll,
}
b.di.InsertValueAtEnd(
v.impl,
dv.ll,
b.di.CreateExpression(nil),
loc,
blk.last,
)
}
func (b diBuilder) DIType(t Type, pos token.Position) DIType {
if ty, ok := b.diTypes[t]; ok {
return ty
}
ty := b.createType(t, pos)
b.diTypes[t] = ty
return ty
}
func (b diBuilder) DIVarParam(f Function, pos token.Position, varName string, vt DIType, argNo int) DIVar {
return b.CreateParameterVariable(
f,
pos,
varName,
argNo,
vt,
)
}
func (b diBuilder) DIVarAuto(f Function, pos token.Position, varName string, vt DIType) DIVar {
return b.CreateAutoVariable(
f,
pos,
varName,
vt,
)
}
func (b diBuilder) DIFile(filename string) DIFile {
return b.createFile(filename)
}
// -----------------------------------------------------------------------------
func (b Builder) SetCurrentDebugLocation(f Function, pos token.Position) {
b.impl.SetCurrentDebugLocation(
uint(pos.Line),
uint(pos.Column),
f.scopeMeta(b.Pkg.DIBuilder(), pos).ll,
f.impl.InstructionDebugLoc(),
)
}
func (b diBuilder) DebugFunction(f Function, pos token.Position) {
// attach debug info to function
f.scopeMeta(b, pos)
}

View File

@@ -338,6 +338,8 @@ func (p Program) tyComplex128() llvm.Type {
// NewPackage creates a new package.
func (p Program) NewPackage(name, pkgPath string) Package {
mod := p.ctx.NewModule(pkgPath)
di := newDIBuilder(p, mod)
cu := di.CreateCompileUnit(name, pkgPath)
// TODO(xsw): Finalize may cause panic, so comment it.
// mod.Finalize()
gbls := make(map[string]Global)
@@ -352,7 +354,7 @@ func (p Program) NewPackage(name, pkgPath string) Package {
// p.needPyInit = false
ret := &aPackage{
mod: mod, vars: gbls, fns: fns, stubs: stubs,
pyobjs: pyobjs, pymods: pymods, strs: strs, named: named, Prog: p}
pyobjs: pyobjs, pymods: pymods, strs: strs, named: named, Prog: p, di: di, cu: cu}
ret.abi.Init(pkgPath)
return ret
}
@@ -589,6 +591,8 @@ type aPackage struct {
abi abi.Builder
Prog Program
di diBuilder
cu CompilationUnit
vars map[string]Global
fns map[string]Function
@@ -706,6 +710,14 @@ func (p Package) AfterInit(b Builder, ret BasicBlock) {
}
}
func (p Package) Finalize() {
p.di.Finalize()
}
func (p Package) DIBuilder() diBuilder {
return p.di
}
// -----------------------------------------------------------------------------
/*

View File

@@ -287,6 +287,24 @@ func (b Builder) Times(n Expr, loop func(i Expr)) {
b.blk.last = blks[2].last
}
// -----------------------------------------------------------------------------
func (b Builder) Debug(v Expr, dv DIVar, scope DIScope, pos token.Position) {
b.Pkg.DIBuilder().Debug(v, dv, scope, pos, b.blk)
}
func (b Builder) DebugValue(v Expr, dv DIVar, scope DIScope, pos token.Position) {
b.Pkg.DIBuilder().DebugValue(v, dv, scope, pos, b.blk)
}
func (b Builder) DIVarParam(f Function, pos token.Position, varName string, vt DIType, argNo int) DIVar {
return b.Pkg.DIBuilder().DIVarParam(f, pos, varName, vt, argNo)
}
func (b Builder) DIVarAuto(f Function, pos token.Position, varName string, vt DIType) DIVar {
return b.Pkg.DIBuilder().DIVarAuto(f, pos, varName, vt)
}
// -----------------------------------------------------------------------------
/*
type caseStmt struct {