1 //===- DWARFLinkerTypeUnit.h ------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_DWARFLINKER_PARALLEL_DWARFLINKERTYPEUNIT_H
10 #define LLVM_DWARFLINKER_PARALLEL_DWARFLINKERTYPEUNIT_H
11 
12 #include "DWARFLinkerUnit.h"
13 #include "llvm/CodeGen/DIE.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
15 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
16 
17 namespace llvm {
18 namespace dwarf_linker {
19 namespace parallel {
20 
21 /// Type Unit is used to represent an artificial compilation unit
22 /// which keeps all type information. This type information is referenced
23 /// from other compilation units.
24 class TypeUnit : public DwarfUnit {
25 public:
26   TypeUnit(LinkingGlobalData &GlobalData, unsigned ID,
27            std::optional<uint16_t> Language, dwarf::FormParams Format,
28            llvm::endianness Endianess);
29 
30   /// Generates DIE tree based on information from TypesMap.
31   void createDIETree(BumpPtrAllocator &Allocator);
32 
33   /// Emits resulting dwarf based on information from DIE tree.
34   Error finishCloningAndEmit(const Triple &TargetTriple);
35 
36   /// Returns global type pool.
37   TypePool &getTypePool() { return Types; }
38 
39   /// TypeUnitAccelInfo extends AccelInfo structure with type specific fileds.
40   /// We need these additional fields to decide whether OutDIE should have an
41   /// accelerator record or not. The TypeEntryBodyPtr can refer to the
42   /// declaration DIE and definition DIE corresponding to the type entry.
43   /// Only one of them would be used in final output. So if TypeUnitAccelInfo
44   /// refers OutDIE which does not match with TypeEntryBodyPtr->getFinalDie()
45   /// then such record should be skipped.
46   struct TypeUnitAccelInfo : public AccelInfo {
47     /// Pointer to the output DIE which owns this accelerator record.
48     DIE *OutDIE = nullptr;
49 
50     /// Pointer to the type entry body.
51     TypeEntryBody *TypeEntryBodyPtr = nullptr;
52   };
53 
54   /// Enumerates all accelerator records and call \p Handler for each.
55   void
56   forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override {
57     AcceleratorRecords.forEach([&](TypeUnitAccelInfo &Info) {
58       // Check whether current record is for the final DIE.
59       assert(Info.TypeEntryBodyPtr != nullptr);
60 
61       if (&Info.TypeEntryBodyPtr->getFinalDie() != Info.OutDIE)
62         return;
63 
64       Info.OutOffset = Info.OutDIE->getOffset();
65       Handler(Info);
66     });
67   }
68 
69   /// Returns index for the specified \p String inside .debug_str_offsets.
70   uint64_t getDebugStrIndex(const StringEntry *String) override {
71     std::unique_lock<std::mutex> LockGuard(DebugStringIndexMapMutex);
72     return DebugStringIndexMap.getValueIndex(String);
73   }
74 
75   /// Adds \p Info to the unit's accelerator records.
76   void saveAcceleratorInfo(const TypeUnitAccelInfo &Info) {
77     AcceleratorRecords.add(Info);
78   }
79 
80 private:
81   /// Type DIEs are partially created at clonning stage. They are organised
82   /// as a tree using type entries. This function links DIEs(corresponding
83   /// to the type entries) into the tree structure.
84   uint64_t finalizeTypeEntryRec(uint64_t OutOffset, DIE *OutDIE,
85                                 TypeEntry *Entry);
86 
87   /// Prepares DIEs to be linked into the tree.
88   void prepareDataForTreeCreation();
89 
90   /// Add specified \p Dir and \p Filename into the line table
91   /// of this type unit.
92   uint32_t addFileNameIntoLinetable(StringEntry *Dir, StringEntry *FileName);
93 
94   std::pair<dwarf::Form, uint8_t> getScalarFormForValue(uint64_t Value) const;
95 
96   uint8_t getSizeByAttrForm(dwarf::Form Form) const;
97 
98   struct CmpStringEntryRef {
99     bool operator()(const StringEntry *LHS, const StringEntry *RHS) const {
100       return LHS->first() < RHS->first();
101     }
102   };
103   struct CmpDirIDStringEntryRef {
104     bool operator()(const std::pair<StringEntry *, uint64_t> &LHS,
105                     const std::pair<StringEntry *, uint64_t> &RHS) const {
106       return LHS.second < RHS.second ||
107              (!(RHS.second < LHS.second) &&
108               LHS.first->first() < RHS.first->first());
109     }
110   };
111 
112   /// The DW_AT_language of this unit.
113   std::optional<uint16_t> Language;
114 
115   /// This unit line table.
116   DWARFDebugLine::LineTable LineTable;
117 
118   /// Data members keeping file names for line table.
119   using DirectoriesMapTy = std::map<StringEntry *, size_t, CmpStringEntryRef>;
120   using FilenamesMapTy = std::map<std::pair<StringEntry *, uint64_t>, size_t,
121                                   CmpDirIDStringEntryRef>;
122 
123   DirectoriesMapTy DirectoriesMap;
124   FilenamesMapTy FileNamesMap;
125 
126   /// Type DIEs tree.
127   TypePool Types;
128 
129   /// List of accelerator entries for this unit.
130   ArrayList<TypeUnitAccelInfo> AcceleratorRecords;
131 
132   /// Guard for DebugStringIndexMap.
133   std::mutex DebugStringIndexMapMutex;
134 };
135 
136 } // end of namespace parallel
137 } // end of namespace dwarf_linker
138 } // end of namespace llvm
139 
140 #endif // LLVM_DWARFLINKER_PARALLEL_DWARFLINKERTYPEUNIT_H
141