1343171Sdim//===- BTFDebug.h -----------------------------------------------*- C++ -*-===//
2343171Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343171Sdim//
7343171Sdim//===----------------------------------------------------------------------===//
8343171Sdim///
9343171Sdim/// \file
10343171Sdim/// This file contains support for writing BTF debug info.
11343171Sdim///
12343171Sdim//===----------------------------------------------------------------------===//
13343171Sdim
14343171Sdim#ifndef LLVM_LIB_TARGET_BPF_BTFDEBUG_H
15343171Sdim#define LLVM_LIB_TARGET_BPF_BTFDEBUG_H
16343171Sdim
17343171Sdim#include "llvm/ADT/StringMap.h"
18343171Sdim#include "llvm/CodeGen/DebugHandlerBase.h"
19360784Sdim#include <set>
20343171Sdim#include <unordered_map>
21343171Sdim#include "BTF.h"
22343171Sdim
23343171Sdimnamespace llvm {
24343171Sdim
25343171Sdimclass AsmPrinter;
26343171Sdimclass BTFDebug;
27343171Sdimclass DIType;
28343171Sdimclass MCStreamer;
29343171Sdimclass MCSymbol;
30343171Sdimclass MachineFunction;
31343171Sdim
32343171Sdim/// The base class for BTF type generation.
33343171Sdimclass BTFTypeBase {
34343171Sdimprotected:
35343171Sdim  uint8_t Kind;
36353358Sdim  bool IsCompleted;
37343171Sdim  uint32_t Id;
38343171Sdim  struct BTF::CommonType BTFType;
39343171Sdim
40343171Sdimpublic:
41353358Sdim  BTFTypeBase() : IsCompleted(false) {}
42343171Sdim  virtual ~BTFTypeBase() = default;
43343171Sdim  void setId(uint32_t Id) { this->Id = Id; }
44343171Sdim  uint32_t getId() { return Id; }
45343171Sdim  uint32_t roundupToBytes(uint32_t NumBits) { return (NumBits + 7) >> 3; }
46343171Sdim  /// Get the size of this BTF type entry.
47343171Sdim  virtual uint32_t getSize() { return BTF::CommonTypeSize; }
48343171Sdim  /// Complete BTF type generation after all related DebugInfo types
49343171Sdim  /// have been visited so their BTF type id's are available
50343171Sdim  /// for cross referece.
51343171Sdim  virtual void completeType(BTFDebug &BDebug) {}
52343171Sdim  /// Emit types for this BTF type entry.
53343171Sdim  virtual void emitType(MCStreamer &OS);
54343171Sdim};
55343171Sdim
56343171Sdim/// Handle several derived types include pointer, const,
57343171Sdim/// volatile, typedef and restrict.
58343171Sdimclass BTFTypeDerived : public BTFTypeBase {
59343171Sdim  const DIDerivedType *DTy;
60353358Sdim  bool NeedsFixup;
61343171Sdim
62343171Sdimpublic:
63353358Sdim  BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup);
64343171Sdim  void completeType(BTFDebug &BDebug);
65343171Sdim  void emitType(MCStreamer &OS);
66353358Sdim  void setPointeeType(uint32_t PointeeType);
67343171Sdim};
68343171Sdim
69343171Sdim/// Handle struct or union forward declaration.
70343171Sdimclass BTFTypeFwd : public BTFTypeBase {
71343171Sdim  StringRef Name;
72343171Sdim
73343171Sdimpublic:
74343171Sdim  BTFTypeFwd(StringRef Name, bool IsUnion);
75343171Sdim  void completeType(BTFDebug &BDebug);
76343171Sdim  void emitType(MCStreamer &OS);
77343171Sdim};
78343171Sdim
79343171Sdim/// Handle int type.
80343171Sdimclass BTFTypeInt : public BTFTypeBase {
81343171Sdim  StringRef Name;
82343171Sdim  uint32_t IntVal; ///< Encoding, offset, bits
83343171Sdim
84343171Sdimpublic:
85343171Sdim  BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits,
86343171Sdim             StringRef TypeName);
87343171Sdim  uint32_t getSize() { return BTFTypeBase::getSize() + sizeof(uint32_t); }
88343171Sdim  void completeType(BTFDebug &BDebug);
89343171Sdim  void emitType(MCStreamer &OS);
90343171Sdim};
91343171Sdim
92343171Sdim/// Handle enumerate type.
93343171Sdimclass BTFTypeEnum : public BTFTypeBase {
94343171Sdim  const DICompositeType *ETy;
95343171Sdim  std::vector<struct BTF::BTFEnum> EnumValues;
96343171Sdim
97343171Sdimpublic:
98343171Sdim  BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues);
99343171Sdim  uint32_t getSize() {
100343171Sdim    return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize;
101343171Sdim  }
102343171Sdim  void completeType(BTFDebug &BDebug);
103343171Sdim  void emitType(MCStreamer &OS);
104343171Sdim};
105343171Sdim
106343171Sdim/// Handle array type.
107343171Sdimclass BTFTypeArray : public BTFTypeBase {
108343171Sdim  struct BTF::BTFArray ArrayInfo;
109343171Sdim
110343171Sdimpublic:
111360784Sdim  BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems);
112343171Sdim  uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; }
113343171Sdim  void completeType(BTFDebug &BDebug);
114343171Sdim  void emitType(MCStreamer &OS);
115343171Sdim};
116343171Sdim
117343171Sdim/// Handle struct/union type.
118343171Sdimclass BTFTypeStruct : public BTFTypeBase {
119343171Sdim  const DICompositeType *STy;
120343171Sdim  bool HasBitField;
121343171Sdim  std::vector<struct BTF::BTFMember> Members;
122343171Sdim
123343171Sdimpublic:
124343171Sdim  BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField,
125343171Sdim                uint32_t NumMembers);
126343171Sdim  uint32_t getSize() {
127343171Sdim    return BTFTypeBase::getSize() + Members.size() * BTF::BTFMemberSize;
128343171Sdim  }
129343171Sdim  void completeType(BTFDebug &BDebug);
130343171Sdim  void emitType(MCStreamer &OS);
131353358Sdim  std::string getName();
132343171Sdim};
133343171Sdim
134343171Sdim/// Handle function pointer.
135343171Sdimclass BTFTypeFuncProto : public BTFTypeBase {
136343171Sdim  const DISubroutineType *STy;
137343171Sdim  std::unordered_map<uint32_t, StringRef> FuncArgNames;
138343171Sdim  std::vector<struct BTF::BTFParam> Parameters;
139343171Sdim
140343171Sdimpublic:
141343171Sdim  BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams,
142343171Sdim                   const std::unordered_map<uint32_t, StringRef> &FuncArgNames);
143343171Sdim  uint32_t getSize() {
144343171Sdim    return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize;
145343171Sdim  }
146343171Sdim  void completeType(BTFDebug &BDebug);
147343171Sdim  void emitType(MCStreamer &OS);
148343171Sdim};
149343171Sdim
150343171Sdim/// Handle subprogram
151343171Sdimclass BTFTypeFunc : public BTFTypeBase {
152343171Sdim  StringRef Name;
153343171Sdim
154343171Sdimpublic:
155360784Sdim  BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope);
156343171Sdim  uint32_t getSize() { return BTFTypeBase::getSize(); }
157343171Sdim  void completeType(BTFDebug &BDebug);
158343171Sdim  void emitType(MCStreamer &OS);
159343171Sdim};
160343171Sdim
161353358Sdim/// Handle variable instances
162353358Sdimclass BTFKindVar : public BTFTypeBase {
163353358Sdim  StringRef Name;
164353358Sdim  uint32_t Info;
165353358Sdim
166353358Sdimpublic:
167353358Sdim  BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo);
168353358Sdim  uint32_t getSize() { return BTFTypeBase::getSize() + 4; }
169353358Sdim  void completeType(BTFDebug &BDebug);
170353358Sdim  void emitType(MCStreamer &OS);
171353358Sdim};
172353358Sdim
173353358Sdim/// Handle data sections
174353358Sdimclass BTFKindDataSec : public BTFTypeBase {
175353358Sdim  AsmPrinter *Asm;
176353358Sdim  std::string Name;
177353358Sdim  std::vector<std::tuple<uint32_t, const MCSymbol *, uint32_t>> Vars;
178353358Sdim
179353358Sdimpublic:
180353358Sdim  BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName);
181353358Sdim  uint32_t getSize() {
182353358Sdim    return BTFTypeBase::getSize() + BTF::BTFDataSecVarSize * Vars.size();
183353358Sdim  }
184353358Sdim  void addVar(uint32_t Id, const MCSymbol *Sym, uint32_t Size) {
185353358Sdim    Vars.push_back(std::make_tuple(Id, Sym, Size));
186353358Sdim  }
187353358Sdim  std::string getName() { return Name; }
188353358Sdim  void completeType(BTFDebug &BDebug);
189353358Sdim  void emitType(MCStreamer &OS);
190353358Sdim};
191353358Sdim
192343171Sdim/// String table.
193343171Sdimclass BTFStringTable {
194343171Sdim  /// String table size in bytes.
195343171Sdim  uint32_t Size;
196343171Sdim  /// A mapping from string table offset to the index
197343171Sdim  /// of the Table. It is used to avoid putting
198343171Sdim  /// duplicated strings in the table.
199360784Sdim  std::map<uint32_t, uint32_t> OffsetToIdMap;
200343171Sdim  /// A vector of strings to represent the string table.
201343171Sdim  std::vector<std::string> Table;
202343171Sdim
203343171Sdimpublic:
204343171Sdim  BTFStringTable() : Size(0) {}
205343171Sdim  uint32_t getSize() { return Size; }
206343171Sdim  std::vector<std::string> &getTable() { return Table; }
207343171Sdim  /// Add a string to the string table and returns its offset
208343171Sdim  /// in the table.
209343171Sdim  uint32_t addString(StringRef S);
210343171Sdim};
211343171Sdim
212343171Sdim/// Represent one func and its type id.
213343171Sdimstruct BTFFuncInfo {
214343171Sdim  const MCSymbol *Label; ///< Func MCSymbol
215343171Sdim  uint32_t TypeId;       ///< Type id referring to .BTF type section
216343171Sdim};
217343171Sdim
218343171Sdim/// Represent one line info.
219343171Sdimstruct BTFLineInfo {
220343171Sdim  MCSymbol *Label;      ///< MCSymbol identifying insn for the lineinfo
221343171Sdim  uint32_t FileNameOff; ///< file name offset in the .BTF string table
222343171Sdim  uint32_t LineOff;     ///< line offset in the .BTF string table
223343171Sdim  uint32_t LineNum;     ///< the line number
224343171Sdim  uint32_t ColumnNum;   ///< the column number
225343171Sdim};
226343171Sdim
227360784Sdim/// Represent one field relocation.
228360784Sdimstruct BTFFieldReloc {
229353358Sdim  const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
230353358Sdim  uint32_t TypeID;        ///< Type ID
231353358Sdim  uint32_t OffsetNameOff; ///< The string to traverse types
232360784Sdim  uint32_t RelocKind;     ///< What to patch the instruction
233353358Sdim};
234353358Sdim
235343171Sdim/// Collect and emit BTF information.
236343171Sdimclass BTFDebug : public DebugHandlerBase {
237343171Sdim  MCStreamer &OS;
238343171Sdim  bool SkipInstruction;
239343171Sdim  bool LineInfoGenerated;
240343171Sdim  uint32_t SecNameOff;
241343171Sdim  uint32_t ArrayIndexTypeId;
242353358Sdim  bool MapDefNotCollected;
243343171Sdim  BTFStringTable StringTable;
244343171Sdim  std::vector<std::unique_ptr<BTFTypeBase>> TypeEntries;
245343171Sdim  std::unordered_map<const DIType *, uint32_t> DIToIdMap;
246353358Sdim  std::map<uint32_t, std::vector<BTFFuncInfo>> FuncInfoTable;
247353358Sdim  std::map<uint32_t, std::vector<BTFLineInfo>> LineInfoTable;
248360784Sdim  std::map<uint32_t, std::vector<BTFFieldReloc>> FieldRelocTable;
249343171Sdim  StringMap<std::vector<std::string>> FileContent;
250353358Sdim  std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries;
251353358Sdim  std::vector<BTFTypeStruct *> StructTypes;
252360784Sdim  std::map<std::string, uint32_t> PatchImms;
253353358Sdim  std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>>
254353358Sdim      FixupDerivedTypes;
255360784Sdim  std::set<const Function *>ProtoFunctions;
256343171Sdim
257343171Sdim  /// Add types to TypeEntries.
258343171Sdim  /// @{
259343171Sdim  /// Add types to TypeEntries and DIToIdMap.
260353358Sdim  uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry, const DIType *Ty);
261343171Sdim  /// Add types to TypeEntries only and return type id.
262343171Sdim  uint32_t addType(std::unique_ptr<BTFTypeBase> TypeEntry);
263343171Sdim  /// @}
264343171Sdim
265343171Sdim  /// IR type visiting functions.
266343171Sdim  /// @{
267343171Sdim  void visitTypeEntry(const DIType *Ty);
268353358Sdim  void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer,
269353358Sdim                      bool SeenPointer);
270353358Sdim  void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId);
271343171Sdim  void visitSubroutineType(
272343171Sdim      const DISubroutineType *STy, bool ForSubprog,
273343171Sdim      const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
274343171Sdim      uint32_t &TypeId);
275353358Sdim  void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,
276353358Sdim                        uint32_t &TypeId);
277353358Sdim  void visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId);
278353358Sdim  void visitStructType(const DICompositeType *STy, bool IsStruct,
279353358Sdim                       uint32_t &TypeId);
280353358Sdim  void visitArrayType(const DICompositeType *ATy, uint32_t &TypeId);
281353358Sdim  void visitEnumType(const DICompositeType *ETy, uint32_t &TypeId);
282353358Sdim  void visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
283353358Sdim                        bool CheckPointer, bool SeenPointer);
284353358Sdim  void visitMapDefType(const DIType *Ty, uint32_t &TypeId);
285343171Sdim  /// @}
286343171Sdim
287343171Sdim  /// Get the file content for the subprogram. Certain lines of the file
288343171Sdim  /// later may be put into string table and referenced by line info.
289343171Sdim  std::string populateFileContent(const DISubprogram *SP);
290343171Sdim
291343171Sdim  /// Construct a line info.
292343171Sdim  void constructLineInfo(const DISubprogram *SP, MCSymbol *Label, uint32_t Line,
293343171Sdim                         uint32_t Column);
294343171Sdim
295353358Sdim  /// Generate types and variables for globals.
296353358Sdim  void processGlobals(bool ProcessingMapDef);
297353358Sdim
298360784Sdim  /// Generate types for function prototypes.
299360784Sdim  void processFuncPrototypes(const Function *);
300353358Sdim
301360784Sdim  /// Generate one field relocation record.
302360784Sdim  void generateFieldReloc(const MCSymbol *ORSym, DIType *RootTy,
303360784Sdim                          StringRef AccessPattern);
304353358Sdim
305353358Sdim  /// Populating unprocessed struct type.
306353358Sdim  unsigned populateStructType(const DIType *Ty);
307353358Sdim
308360784Sdim  /// Process relocation instructions.
309360784Sdim  void processReloc(const MachineOperand &MO);
310353358Sdim
311343171Sdim  /// Emit common header of .BTF and .BTF.ext sections.
312343171Sdim  void emitCommonHeader();
313343171Sdim
314343171Sdim  /// Emit the .BTF section.
315343171Sdim  void emitBTFSection();
316343171Sdim
317343171Sdim  /// Emit the .BTF.ext section.
318343171Sdim  void emitBTFExtSection();
319343171Sdim
320343171Sdimprotected:
321343171Sdim  /// Gather pre-function debug information.
322343171Sdim  void beginFunctionImpl(const MachineFunction *MF) override;
323343171Sdim
324343171Sdim  /// Post process after all instructions in this function are processed.
325343171Sdim  void endFunctionImpl(const MachineFunction *MF) override;
326343171Sdim
327343171Sdimpublic:
328343171Sdim  BTFDebug(AsmPrinter *AP);
329343171Sdim
330353358Sdim  ///
331353358Sdim  bool InstLower(const MachineInstr *MI, MCInst &OutMI);
332353358Sdim
333343171Sdim  /// Get the special array index type id.
334343171Sdim  uint32_t getArrayIndexTypeId() {
335343171Sdim    assert(ArrayIndexTypeId);
336343171Sdim    return ArrayIndexTypeId;
337343171Sdim  }
338343171Sdim
339343171Sdim  /// Add string to the string table.
340343171Sdim  size_t addString(StringRef S) { return StringTable.addString(S); }
341343171Sdim
342343171Sdim  /// Get the type id for a particular DIType.
343343171Sdim  uint32_t getTypeId(const DIType *Ty) {
344343171Sdim    assert(Ty && "Invalid null Type");
345343171Sdim    assert(DIToIdMap.find(Ty) != DIToIdMap.end() &&
346343171Sdim           "DIType not added in the BDIToIdMap");
347343171Sdim    return DIToIdMap[Ty];
348343171Sdim  }
349343171Sdim
350343171Sdim  void setSymbolSize(const MCSymbol *Symbol, uint64_t Size) override {}
351343171Sdim
352343171Sdim  /// Process beginning of an instruction.
353343171Sdim  void beginInstruction(const MachineInstr *MI) override;
354343171Sdim
355343171Sdim  /// Complete all the types and emit the BTF sections.
356343171Sdim  void endModule() override;
357343171Sdim};
358343171Sdim
359343171Sdim} // end namespace llvm
360343171Sdim
361343171Sdim#endif
362