github.com/bir3/gocompiler@v0.9.2202/src/cmd/internal/goobj/funcinfo.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package goobj 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "github.com/bir3/gocompiler/src/internal/abi" 11 ) 12 13 // CUFileIndex is used to index the filenames that are stored in the 14 // per-package/per-CU FileList. 15 type CUFileIndex uint32 16 17 // FuncInfo is serialized as a symbol (aux symbol). The symbol data is 18 // the binary encoding of the struct below. 19 type FuncInfo struct { 20 Args uint32 21 Locals uint32 22 FuncID abi.FuncID 23 FuncFlag abi.FuncFlag 24 StartLine int32 25 File []CUFileIndex 26 InlTree []InlTreeNode 27 } 28 29 func (a *FuncInfo) Write(w *bytes.Buffer) { 30 writeUint8 := func(x uint8) { 31 w.WriteByte(x) 32 } 33 var b [4]byte 34 writeUint32 := func(x uint32) { 35 binary.LittleEndian.PutUint32(b[:], x) 36 w.Write(b[:]) 37 } 38 39 writeUint32(a.Args) 40 writeUint32(a.Locals) 41 writeUint8(uint8(a.FuncID)) 42 writeUint8(uint8(a.FuncFlag)) 43 writeUint8(0) // pad to uint32 boundary 44 writeUint8(0) 45 writeUint32(uint32(a.StartLine)) 46 47 writeUint32(uint32(len(a.File))) 48 for _, f := range a.File { 49 writeUint32(uint32(f)) 50 } 51 writeUint32(uint32(len(a.InlTree))) 52 for i := range a.InlTree { 53 a.InlTree[i].Write(w) 54 } 55 } 56 57 // FuncInfoLengths is a cache containing a roadmap of offsets and 58 // lengths for things within a serialized FuncInfo. Each length field 59 // stores the number of items (e.g. files, inltree nodes, etc), and the 60 // corresponding "off" field stores the byte offset of the start of 61 // the items in question. 62 type FuncInfoLengths struct { 63 NumFile uint32 64 FileOff uint32 65 NumInlTree uint32 66 InlTreeOff uint32 67 Initialized bool 68 } 69 70 func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { 71 var result FuncInfoLengths 72 73 // Offset to the number of the file table. This value is determined by counting 74 // the number of bytes until we write funcdataoff to the file. 75 const numfileOff = 16 76 result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:]) 77 result.FileOff = numfileOff + 4 78 79 numinltreeOff := result.FileOff + 4*result.NumFile 80 result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:]) 81 result.InlTreeOff = numinltreeOff + 4 82 83 result.Initialized = true 84 85 return result 86 } 87 88 func (*FuncInfo) ReadArgs(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } 89 90 func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32(b[4:]) } 91 92 func (*FuncInfo) ReadFuncID(b []byte) abi.FuncID { return abi.FuncID(b[8]) } 93 94 func (*FuncInfo) ReadFuncFlag(b []byte) abi.FuncFlag { return abi.FuncFlag(b[9]) } 95 96 func (*FuncInfo) ReadStartLine(b []byte) int32 { return int32(binary.LittleEndian.Uint32(b[12:])) } 97 98 func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex { 99 return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:])) 100 } 101 102 func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode { 103 const inlTreeNodeSize = 4 * 6 104 var result InlTreeNode 105 result.Read(b[inltreeoff+k*inlTreeNodeSize:]) 106 return result 107 } 108 109 // InlTreeNode is the serialized form of FileInfo.InlTree. 110 type InlTreeNode struct { 111 Parent int32 112 File CUFileIndex 113 Line int32 114 Func SymRef 115 ParentPC int32 116 } 117 118 func (inl *InlTreeNode) Write(w *bytes.Buffer) { 119 var b [4]byte 120 writeUint32 := func(x uint32) { 121 binary.LittleEndian.PutUint32(b[:], x) 122 w.Write(b[:]) 123 } 124 writeUint32(uint32(inl.Parent)) 125 writeUint32(uint32(inl.File)) 126 writeUint32(uint32(inl.Line)) 127 writeUint32(inl.Func.PkgIdx) 128 writeUint32(inl.Func.SymIdx) 129 writeUint32(uint32(inl.ParentPC)) 130 } 131 132 // Read an InlTreeNode from b, return the remaining bytes. 133 func (inl *InlTreeNode) Read(b []byte) []byte { 134 readUint32 := func() uint32 { 135 x := binary.LittleEndian.Uint32(b) 136 b = b[4:] 137 return x 138 } 139 inl.Parent = int32(readUint32()) 140 inl.File = CUFileIndex(readUint32()) 141 inl.Line = int32(readUint32()) 142 inl.Func = SymRef{readUint32(), readUint32()} 143 inl.ParentPC = int32(readUint32()) 144 return b 145 }