diff options
Diffstat (limited to 'src/cmd/internal')
-rw-r--r-- | src/cmd/internal/dwarf/dwarf.go | 130 | ||||
-rw-r--r-- | src/cmd/internal/obj/link.go | 53 | ||||
-rw-r--r-- | src/cmd/internal/obj/objfile.go | 17 | ||||
-rw-r--r-- | src/cmd/internal/obj/plist.go | 18 | ||||
-rw-r--r-- | src/cmd/internal/obj/x86/a.out.go | 117 | ||||
-rw-r--r-- | src/cmd/internal/obj/x86/obj6.go | 39 | ||||
-rw-r--r-- | src/cmd/internal/objabi/symkind.go | 1 | ||||
-rw-r--r-- | src/cmd/internal/objabi/symkind_string.go | 4 |
8 files changed, 285 insertions, 94 deletions
diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index b58052beb3..2b034257a6 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -15,6 +15,9 @@ import ( // InfoPrefix is the prefix for all the symbols containing DWARF info entries. const InfoPrefix = "go.info." +// RangePrefix is the prefix for all the symbols containing DWARF location lists. +const LocPrefix = "go.loc." + // RangePrefix is the prefix for all the symbols containing DWARF range lists. const RangePrefix = "go.range." @@ -23,13 +26,31 @@ type Sym interface { Len() int64 } +// A Location represents a variable's location at a particular PC range. +// It becomes a location list entry in the DWARF. +type Location struct { + StartPC, EndPC int64 + Pieces []Piece +} + +// A Piece represents the location of a particular part of a variable. +// It becomes part of a location list entry (a DW_OP_piece) in the DWARF. +type Piece struct { + Length int64 + StackOffset int32 + RegNum int16 + Missing bool + OnStack bool // if true, RegNum is unset. +} + // A Var represents a local variable or a function parameter. type Var struct { - Name string - Abbrev int // Either DW_ABRV_AUTO or DW_ABRV_PARAM - StackOffset int32 - Scope int32 - Type Sym + Name string + Abbrev int // Either DW_ABRV_AUTO or DW_ABRV_PARAM + StackOffset int32 + LocationList []Location + Scope int32 + Type Sym } // A Scope represents a lexical scope. All variables declared within a @@ -205,7 +226,7 @@ const ( ) // Index into the abbrevs table below. -// Keep in sync with ispubname() and ispubtype() below. +// Keep in sync with ispubname() and ispubtype() in ld/dwarf.go. // ispubtype considers >= NULLTYPE public const ( DW_ABRV_NULL = iota @@ -709,31 +730,30 @@ func HasChildren(die *DWDie) bool { // PutFunc writes a DIE for a function to s. // It also writes child DIEs for each variable in vars. -func PutFunc(ctxt Context, s, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error { - Uleb128put(ctxt, s, DW_ABRV_FUNCTION) - putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) - putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC) - putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, size, startPC) - putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) +func PutFunc(ctxt Context, info, loc, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error { + Uleb128put(ctxt, info, DW_ABRV_FUNCTION) + putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) + putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC) + putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, size, startPC) + putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) var ev int64 if external { ev = 1 } - putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0) + putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0) if len(scopes) > 0 { var encbuf [20]byte - if putscope(ctxt, s, ranges, startPC, 0, scopes, encbuf[:0]) < int32(len(scopes)) { + if putscope(ctxt, info, loc, ranges, startPC, 0, scopes, encbuf[:0]) < int32(len(scopes)) { return errors.New("multiple toplevel scopes") } } - - Uleb128put(ctxt, s, 0) + Uleb128put(ctxt, info, 0) return nil } -func putscope(ctxt Context, s, ranges Sym, startPC Sym, curscope int32, scopes []Scope, encbuf []byte) int32 { +func putscope(ctxt Context, info, loc, ranges, startPC Sym, curscope int32, scopes []Scope, encbuf []byte) int32 { for _, v := range scopes[curscope].Vars { - putvar(ctxt, s, v, encbuf) + putvar(ctxt, info, loc, v, startPC, encbuf) } this := curscope curscope++ @@ -744,12 +764,12 @@ func putscope(ctxt Context, s, ranges Sym, startPC Sym, curscope int32, scopes [ } if len(scope.Ranges) == 1 { - Uleb128put(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE) - putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, startPC) - putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, startPC) + Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE) + putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, startPC) + putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, startPC) } else { - Uleb128put(ctxt, s, DW_ABRV_LEXICAL_BLOCK_RANGES) - putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ranges.Len(), ranges) + Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES) + putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ranges.Len(), ranges) ctxt.AddAddress(ranges, nil, -1) ctxt.AddAddress(ranges, startPC, 0) @@ -761,26 +781,66 @@ func putscope(ctxt Context, s, ranges Sym, startPC Sym, curscope int32, scopes [ ctxt.AddAddress(ranges, nil, 0) } - curscope = putscope(ctxt, s, ranges, startPC, curscope, scopes, encbuf) + curscope = putscope(ctxt, info, loc, ranges, startPC, curscope, scopes, encbuf) - Uleb128put(ctxt, s, 0) + Uleb128put(ctxt, info, 0) } return curscope } -func putvar(ctxt Context, s Sym, v *Var, encbuf []byte) { +func putvar(ctxt Context, info, loc Sym, v *Var, startPC Sym, encbuf []byte) { n := v.Name - Uleb128put(ctxt, s, int64(v.Abbrev)) - putattr(ctxt, s, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) - loc := append(encbuf[:0], DW_OP_call_frame_cfa) - if v.StackOffset != 0 { - loc = append(loc, DW_OP_consts) - loc = AppendSleb128(loc, int64(v.StackOffset)) - loc = append(loc, DW_OP_plus) + Uleb128put(ctxt, info, int64(v.Abbrev)) + putattr(ctxt, info, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) + if v.Abbrev == DW_ABRV_AUTO_LOCLIST || v.Abbrev == DW_ABRV_PARAM_LOCLIST { + putattr(ctxt, info, v.Abbrev, DW_FORM_sec_offset, DW_CLS_PTR, int64(loc.Len()), loc) + addLocList(ctxt, loc, startPC, v, encbuf) + } else { + loc := append(encbuf[:0], DW_OP_call_frame_cfa) + if v.StackOffset != 0 { + loc = append(loc, DW_OP_consts) + loc = AppendSleb128(loc, int64(v.StackOffset)) + loc = append(loc, DW_OP_plus) + } + putattr(ctxt, info, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) + } + putattr(ctxt, info, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) +} + +func addLocList(ctxt Context, listSym, startPC Sym, v *Var, encbuf []byte) { + // Base address entry: max ptr followed by the base address. + ctxt.AddInt(listSym, ctxt.PtrSize(), ^0) + ctxt.AddAddress(listSym, startPC, 0) + for _, entry := range v.LocationList { + ctxt.AddInt(listSym, ctxt.PtrSize(), entry.StartPC) + ctxt.AddInt(listSym, ctxt.PtrSize(), entry.EndPC) + locBuf := encbuf[:0] + for _, piece := range entry.Pieces { + if !piece.Missing { + if piece.OnStack { + locBuf = append(locBuf, DW_OP_fbreg) + locBuf = AppendSleb128(locBuf, int64(piece.StackOffset)) + } else { + if piece.RegNum < 32 { + locBuf = append(locBuf, DW_OP_reg0+byte(piece.RegNum)) + } else { + locBuf = append(locBuf, DW_OP_regx) + locBuf = AppendUleb128(locBuf, uint64(piece.RegNum)) + } + } + } + if len(entry.Pieces) > 1 { + locBuf = append(locBuf, DW_OP_piece) + locBuf = AppendUleb128(locBuf, uint64(piece.Length)) + } + } + ctxt.AddInt(listSym, 2, int64(len(locBuf))) + ctxt.AddBytes(listSym, locBuf) } - putattr(ctxt, s, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) - putattr(ctxt, s, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) + // End list + ctxt.AddInt(listSym, ctxt.PtrSize(), 0) + ctxt.AddInt(listSym, ctxt.PtrSize(), 0) } // VarsByOffset attaches the methods of sort.Interface to []*Var, diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index d49bc8c564..68e1b70ac0 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -330,7 +330,8 @@ type FuncInfo struct { Autom []*Auto Pcln Pcln - dwarfSym *LSym + dwarfInfoSym *LSym + dwarfLocSym *LSym dwarfRangesSym *LSym GCArgs LSym @@ -476,25 +477,26 @@ type Pcdata struct { // Link holds the context for writing object code from a compiler // to be linker input or for reading that input into the linker. type Link struct { - Headtype objabi.HeadType - Arch *LinkArch - Debugasm bool - Debugvlog bool - Debugpcln string - Flag_shared bool - Flag_dynlink bool - Flag_optimize bool - Bso *bufio.Writer - Pathname string - hashmu sync.Mutex // protects hash - hash map[string]*LSym // name -> sym mapping - statichash map[string]*LSym // name -> sym mapping for static syms - PosTable src.PosTable - InlTree InlTree // global inlining tree used by gc/inl.go - Imports []string - DiagFunc func(string, ...interface{}) - DebugInfo func(fn *LSym, curfn interface{}) []dwarf.Scope // if non-nil, curfn is a *gc.Node - Errors int + Headtype objabi.HeadType + Arch *LinkArch + Debugasm bool + Debugvlog bool + Debugpcln string + Flag_shared bool + Flag_dynlink bool + Flag_optimize bool + Flag_locationlists bool + Bso *bufio.Writer + Pathname string + hashmu sync.Mutex // protects hash + hash map[string]*LSym // name -> sym mapping + statichash map[string]*LSym // name -> sym mapping for static syms + PosTable src.PosTable + InlTree InlTree // global inlining tree used by gc/inl.go + Imports []string + DiagFunc func(string, ...interface{}) + DebugInfo func(fn *LSym, curfn interface{}) []dwarf.Scope // if non-nil, curfn is a *gc.Node + Errors int Framepointer_enabled bool @@ -533,9 +535,10 @@ func (ctxt *Link) FixedFrameSize() int64 { // LinkArch is the definition of a single architecture. type LinkArch struct { *sys.Arch - Init func(*Link) - Preprocess func(*Link, *LSym, ProgAlloc) - Assemble func(*Link, *LSym, ProgAlloc) - Progedit func(*Link, *Prog, ProgAlloc) - UnaryDst map[As]bool // Instruction takes one operand, a destination. + Init func(*Link) + Preprocess func(*Link, *LSym, ProgAlloc) + Assemble func(*Link, *LSym, ProgAlloc) + Progedit func(*Link, *Prog, ProgAlloc) + UnaryDst map[As]bool // Instruction takes one operand, a destination. + DWARFRegisters map[int16]int16 } diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index e309c5f7e7..539d013037 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -465,15 +465,18 @@ func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64 } // dwarfSym returns the DWARF symbols for TEXT symbol. -func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfRangesSym *LSym) { +func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfLocSym, dwarfRangesSym *LSym) { if s.Type != objabi.STEXT { ctxt.Diag("dwarfSym of non-TEXT %v", s) } - if s.Func.dwarfSym == nil { - s.Func.dwarfSym = ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name) + if s.Func.dwarfInfoSym == nil { + s.Func.dwarfInfoSym = ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name) + if ctxt.Flag_locationlists { + s.Func.dwarfLocSym = ctxt.LookupDerived(s, dwarf.LocPrefix+s.Name) + } s.Func.dwarfRangesSym = ctxt.LookupDerived(s, dwarf.RangePrefix+s.Name) } - return s.Func.dwarfSym, s.Func.dwarfRangesSym + return s.Func.dwarfInfoSym, s.Func.dwarfLocSym, s.Func.dwarfRangesSym } func (s *LSym) Len() int64 { @@ -483,15 +486,15 @@ func (s *LSym) Len() int64 { // populateDWARF fills in the DWARF Debugging Information Entries for TEXT symbol s. // The DWARFs symbol must already have been initialized in InitTextSym. func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym) { - dsym, drsym := ctxt.dwarfSym(s) - if dsym.Size != 0 { + info, loc, ranges := ctxt.dwarfSym(s) + if info.Size != 0 { ctxt.Diag("makeFuncDebugEntry double process %v", s) } var scopes []dwarf.Scope if ctxt.DebugInfo != nil { scopes = ctxt.DebugInfo(s, curfn) } - err := dwarf.PutFunc(dwCtxt{ctxt}, dsym, drsym, s.Name, !s.Static(), s, s.Size, scopes) + err := dwarf.PutFunc(dwCtxt{ctxt}, info, loc, ranges, s.Name, !s.Static(), s, s.Size, scopes) if err != nil { ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err) } diff --git a/src/cmd/internal/obj/plist.go b/src/cmd/internal/obj/plist.go index 861da88703..1bb05aedfa 100644 --- a/src/cmd/internal/obj/plist.go +++ b/src/cmd/internal/obj/plist.go @@ -136,13 +136,17 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int) { ctxt.Text = append(ctxt.Text, s) // Set up DWARF entries for s. - dsym, drsym := ctxt.dwarfSym(s) - dsym.Type = objabi.SDWARFINFO - dsym.Set(AttrDuplicateOK, s.DuplicateOK()) - drsym.Type = objabi.SDWARFRANGE - drsym.Set(AttrDuplicateOK, s.DuplicateOK()) - ctxt.Data = append(ctxt.Data, dsym) - ctxt.Data = append(ctxt.Data, drsym) + info, loc, ranges := ctxt.dwarfSym(s) + info.Type = objabi.SDWARFINFO + info.Set(AttrDuplicateOK, s.DuplicateOK()) + if loc != nil { + loc.Type = objabi.SDWARFLOC + loc.Set(AttrDuplicateOK, s.DuplicateOK()) + ctxt.Data = append(ctxt.Data, loc) + } + ranges.Type = objabi.SDWARFRANGE + ranges.Set(AttrDuplicateOK, s.DuplicateOK()) + ctxt.Data = append(ctxt.Data, info, ranges) // Set up the function's gcargs and gclocals. // They will be filled in later if needed. diff --git a/src/cmd/internal/obj/x86/a.out.go b/src/cmd/internal/obj/x86/a.out.go index 04f9ef68a4..92d358ba4e 100644 --- a/src/cmd/internal/obj/x86/a.out.go +++ b/src/cmd/internal/obj/x86/a.out.go @@ -1006,3 +1006,120 @@ const ( T_64 = 1 << 6 T_GOTYPE = 1 << 7 ) + +// https://www.uclibc.org/docs/psABI-x86_64.pdf, figure 3.36 +var AMD64DWARFRegisters = map[int16]int16{ + REG_AX: 0, + REG_DX: 1, + REG_CX: 2, + REG_BX: 3, + REG_SI: 4, + REG_DI: 5, + REG_BP: 6, + REG_SP: 7, + REG_R8: 8, + REG_R9: 9, + REG_R10: 10, + REG_R11: 11, + REG_R12: 12, + REG_R13: 13, + REG_R14: 14, + REG_R15: 15, + // 16 is "Return Address RA", whatever that is. + // XMM registers. %xmmN => XN. + REG_X0: 17, + REG_X1: 18, + REG_X2: 19, + REG_X3: 20, + REG_X4: 21, + REG_X5: 22, + REG_X6: 23, + REG_X7: 24, + REG_X8: 25, + REG_X9: 26, + REG_X10: 27, + REG_X11: 28, + REG_X12: 29, + REG_X13: 30, + REG_X14: 31, + REG_X15: 32, + // ST registers. %stN => FN. + REG_F0: 33, + REG_F1: 34, + REG_F2: 35, + REG_F3: 36, + REG_F4: 37, + REG_F5: 38, + REG_F6: 39, + REG_F7: 40, + // MMX registers. %mmN => MN. + REG_M0: 41, + REG_M1: 42, + REG_M2: 43, + REG_M3: 44, + REG_M4: 45, + REG_M5: 46, + REG_M6: 47, + REG_M7: 48, + // 48 is flags, which doesn't have a name. + REG_ES: 50, + REG_CS: 51, + REG_SS: 52, + REG_DS: 53, + REG_FS: 54, + REG_GS: 55, + // 58 and 59 are {fs,gs}base, which don't have names. + REG_TR: 62, + REG_LDTR: 63, + // 64-66 are mxcsr, fcw, fsw, which don't have names. +} + +// https://www.uclibc.org/docs/psABI-i386.pdf, table 2.14 +var X86DWARFRegisters = map[int16]int16{ + REG_AX: 0, + REG_CX: 1, + REG_DX: 2, + REG_BX: 3, + REG_SP: 4, + REG_BP: 5, + REG_SI: 6, + REG_DI: 7, + // 8 is "Return Address RA", whatever that is. + // 9 is flags, which doesn't have a name. + // ST registers. %stN => FN. + REG_F0: 11, + REG_F1: 12, + REG_F2: 13, + REG_F3: 14, + REG_F4: 15, + REG_F5: 16, + REG_F6: 17, + REG_F7: 18, + // XMM registers. %xmmN => XN. + REG_X0: 21, + REG_X1: 22, + REG_X2: 23, + REG_X3: 24, + REG_X4: 25, + REG_X5: 26, + REG_X6: 27, + REG_X7: 28, + // MMX registers. %mmN => MN. + REG_M0: 29, + REG_M1: 30, + REG_M2: 31, + REG_M3: 32, + REG_M4: 33, + REG_M5: 34, + REG_M6: 35, + REG_M7: 36, + // 39 is mxcsr, which doesn't have a name. + REG_ES: 40, + REG_CS: 41, + REG_SS: 42, + REG_DS: 43, + REG_FS: 44, + REG_GS: 45, + REG_TR: 48, + REG_LDTR: 49, +} diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index d34f0aeaa6..27873e0824 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -1231,28 +1231,31 @@ var unaryDst = map[obj.As]bool{ } var Linkamd64 = obj.LinkArch{ - Arch: sys.ArchAMD64, - Init: instinit, - Preprocess: preprocess, - Assemble: span6, - Progedit: progedit, - UnaryDst: unaryDst, + Arch: sys.ArchAMD64, + Init: instinit, + Preprocess: preprocess, + Assemble: span6, + Progedit: progedit, + UnaryDst: unaryDst, + DWARFRegisters: AMD64DWARFRegisters, } var Linkamd64p32 = obj.LinkArch{ - Arch: sys.ArchAMD64P32, - Init: instinit, - Preprocess: preprocess, - Assemble: span6, - Progedit: progedit, - UnaryDst: unaryDst, + Arch: sys.ArchAMD64P32, + Init: instinit, + Preprocess: preprocess, + Assemble: span6, + Progedit: progedit, + UnaryDst: unaryDst, + DWARFRegisters: AMD64DWARFRegisters, } var Link386 = obj.LinkArch{ - Arch: sys.Arch386, - Init: instinit, - Preprocess: preprocess, - Assemble: span6, - Progedit: progedit, - UnaryDst: unaryDst, + Arch: sys.Arch386, + Init: instinit, + Preprocess: preprocess, + Assemble: span6, + Progedit: progedit, + UnaryDst: unaryDst, + DWARFRegisters: AMD64DWARFRegisters, } diff --git a/src/cmd/internal/objabi/symkind.go b/src/cmd/internal/objabi/symkind.go index b037e9e4ed..ac91824d17 100644 --- a/src/cmd/internal/objabi/symkind.go +++ b/src/cmd/internal/objabi/symkind.go @@ -57,4 +57,5 @@ const ( // Debugging data SDWARFINFO SDWARFRANGE + SDWARFLOC ) diff --git a/src/cmd/internal/objabi/symkind_string.go b/src/cmd/internal/objabi/symkind_string.go index 5123dc7097..3064c8ee05 100644 --- a/src/cmd/internal/objabi/symkind_string.go +++ b/src/cmd/internal/objabi/symkind_string.go @@ -4,9 +4,9 @@ package objabi import "fmt" -const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGE" +const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOC" -var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72} +var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81} func (i SymKind) String() string { if i >= SymKind(len(_SymKind_index)-1) { |