LLVM: lib/DWARFLinker/Parallel/DWARFLinkerTypeUnit.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

12

13using namespace llvm;

16

21 AcceleratorRecords(&GlobalData.getAllocator()) {

22

23 UnitName = "__artificial_type_unit";

24

26

27

29 LineTable.Prologue.MinInstLength = 1;

30 LineTable.Prologue.MaxOpsPerInst = 1;

31 LineTable.Prologue.DefaultIsStmt = 1;

32 LineTable.Prologue.LineBase = -5;

33 LineTable.Prologue.LineRange = 14;

34 LineTable.Prologue.OpcodeBase = 13;

35 LineTable.Prologue.StandardOpcodeLengths = {0, 1, 1, 1, 1, 0,

36 0, 0, 1, 0, 0, 1};

37

39}

40

42 prepareDataForTreeCreation();

43

44

45

52

53 DIEGenerator DIETreeGenerator(Allocator, *this);

55

56

57 DIE *UnitDIE = DIETreeGenerator.createDIE(dwarf::DW_TAG_compile_unit, 0);

60

62 ProducerString += "llvm DWARFLinkerParallel library version ";

65 {OutOffset},

66 GlobalData.getStringPool().insert(ProducerString.str()).first},

67 PatchesOffsets);

68 OutOffset += DIETreeGenerator

70 dwarf::DW_FORM_strp)

71 .second;

72

73 if (Language) {

74 OutOffset += DIETreeGenerator

76 dwarf::DW_FORM_data2, *Language)

77 .second;

78 }

79

83 PatchesOffsets);

84 OutOffset += DIETreeGenerator

86 dwarf::DW_FORM_strp)

87 .second;

88

89 if (!LineTable.Prologue.FileNames.empty()) {

91 DebugOffsetPatch{OutOffset, &DebugLineSection}, PatchesOffsets);

92

93 OutOffset += DIETreeGenerator

95 dwarf::DW_FORM_sec_offset, 0xbaddef)

96 .second;

97 }

98

101 PatchesOffsets);

102 OutOffset += DIETreeGenerator

104 dwarf::DW_FORM_strp)

105 .second;

106

108

109

110

111 OutOffset += DIETreeGenerator

113 dwarf::DW_FORM_sec_offset,

115 .second;

116 }

117

119 OutOffset =

120 finalizeTypeEntryRec(UnitDIE->getOffset(), UnitDIE, Types.getRoot());

121

122

123 for (uint64_t *OffsetPtr : PatchesOffsets)

125

127 });

128}

129

130void TypeUnit::prepareDataForTreeCreation() {

133

134

135

136

138

141

142 Types.sortTypes();

143 });

144 }

145

148

153 return LHS.Directory->first() < RHS.Directory->first() ||

154 (!(RHS.Directory->first() < LHS.Directory->first()) &&

155 LHS.FilePath->first() < RHS.FilePath->first());

156 };

157

158 DebugInfoSection.ListDebugTypeDeclFilePatch.sort(PatchesComparator);

159 }

160

161

163 getScalarFormForValue(

164 DebugInfoSection.ListDebugTypeDeclFilePatch.size())

165 .first;

166

167 DebugInfoSection.ListDebugTypeDeclFilePatch.forEach(

168 [&](DebugTypeDeclFilePatch &Patch) {

172 .str()

173 .c_str());

175 return;

176

177 uint32_t FileIdx =

179

180 unsigned DIESize = Patch.Die->getSize();

181 DIEGenerator DIEGen(Patch.Die, Types.getThreadLocalAllocator(),

182 *this);

183

184 DIESize += DIEGen

185 .addScalarAttribute(dwarf::DW_AT_decl_file,

186 DeclFileForm, FileIdx)

187 .second;

189 });

190 });

191

192 if (GlobalData.getOptions().AllowNonDeterministicOutput) {

193

195 forEach([&](SectionDescriptor &OutSection) {

196 std::function<bool(const DebugStrPatch &LHS, const DebugStrPatch &RHS)>

197 StrPatchesComparator =

198 [&](const DebugStrPatch &LHS, const DebugStrPatch &RHS) {

199 return LHS.String->getKey() < RHS.String->getKey();

200 };

201 OutSection.ListDebugStrPatch.sort(StrPatchesComparator);

202

203 std::function<bool(const DebugTypeStrPatch &LHS,

204 const DebugTypeStrPatch &RHS)>

205 TypeStrPatchesComparator = [&](const DebugTypeStrPatch &LHS,

206 const DebugTypeStrPatch &RHS) {

207 return LHS.String->getKey() < RHS.String->getKey();

208 };

209 OutSection.ListDebugTypeStrPatch.sort(TypeStrPatchesComparator);

210 });

211 });

212 }

213

214 if (GlobalData.getOptions().AllowNonDeterministicOutput) {

215

217 forEach([&](SectionDescriptor &OutSection) {

218 std::function<bool(const DebugLineStrPatch &LHS,

219 const DebugLineStrPatch &RHS)>

220 LineStrPatchesComparator = [&](const DebugLineStrPatch &LHS,

221 const DebugLineStrPatch &RHS) {

222 return LHS.String->getKey() < RHS.String->getKey();

223 };

224 OutSection.ListDebugLineStrPatch.sort(LineStrPatchesComparator);

225

226 std::function<bool(const DebugTypeLineStrPatch &LHS,

227 const DebugTypeLineStrPatch &RHS)>

228 TypeLineStrPatchesComparator =

229 [&](const DebugTypeLineStrPatch &LHS,

230 const DebugTypeLineStrPatch &RHS) {

231 return LHS.String->getKey() < RHS.String->getKey();

232 };

233 OutSection.ListDebugTypeLineStrPatch.sort(TypeLineStrPatchesComparator);

234 });

235 });

236 }

237}

238

239uint64_t TypeUnit::finalizeTypeEntryRec(uint64_t OutOffset, DIE *OutDIE,

241 bool HasChildren = Entry->getValue().load()->Children.empty();

242 DIEGenerator DIEGen(OutDIE, Types.getThreadLocalAllocator(), *this);

243 OutOffset += DIEGen.finalizeAbbreviations(HasChildren, nullptr);

244 OutOffset += OutDIE->getSize() - 1;

245

246 if (HasChildren) {

247 Entry->getValue().load()->Children.forEach([&](TypeEntry *ChildEntry) {

248 DIE *ChildDIE = &ChildEntry->getValue().load()->getFinalDie();

249 DIEGen.addChild(ChildDIE);

250

252

253 OutOffset = finalizeTypeEntryRec(OutOffset, ChildDIE, ChildEntry);

254 });

255

256

257 OutOffset += sizeof(int8_t);

258 }

259

261 return OutOffset;

262}

263

264uint32_t TypeUnit::addFileNameIntoLinetable(StringEntry *Dir,

266 uint32_t DirIdx = 0;

267

268 if (Dir->first() == "") {

269 DirIdx = 0;

270 } else {

271 DirectoriesMapTy::iterator DirEntry = DirectoriesMap.find(Dir);

272 if (DirEntry == DirectoriesMap.end()) {

273

274 assert(LineTable.Prologue.IncludeDirectories.size() < UINT32_MAX);

275 DirIdx = LineTable.Prologue.IncludeDirectories.size();

276 DirectoriesMap.insert({Dir, DirIdx});

277 LineTable.Prologue.IncludeDirectories.push_back(

280 } else {

281 DirIdx = DirEntry->second;

282 }

283

285 DirIdx++;

286 }

287

288 auto [FileEntry, Inserted] = FileNamesMap.try_emplace(

289 {FileName, DirIdx}, LineTable.Prologue.FileNames.size());

290 if (Inserted) {

291

292 assert(LineTable.Prologue.FileNames.size() < UINT32_MAX);

293 LineTable.Prologue.FileNames.push_back(DWARFDebugLine::FileNameEntry());

295 dwarf::DW_FORM_string, FileName->getKeyData());

296 LineTable.Prologue.FileNames.back().DirIdx = DirIdx;

297 }

298

299 uint32_t FileIdx = FileEntry->second;

300 return getVersion() < 5 ? FileIdx + 1 : FileIdx;

301}

302

303std::pair<dwarf::Form, uint8_t>

304TypeUnit::getScalarFormForValue(uint64_t Value) const {

305 if (Value > 0xFFFFFFFF)

306 return std::make_pair(dwarf::DW_FORM_data8, 8);

307

308 if (Value > 0xFFFF)

309 return std::make_pair(dwarf::DW_FORM_data4, 4);

310

311 if (Value > 0xFF)

312 return std::make_pair(dwarf::DW_FORM_data2, 2);

313

314 return std::make_pair(dwarf::DW_FORM_data1, 1);

315}

316

317uint8_t TypeUnit::getSizeByAttrForm(dwarf::Form Form) const {

318 if (Form == dwarf::DW_FORM_data1)

319 return 1;

320

321 if (Form == dwarf::DW_FORM_data2)

322 return 2;

323

324 if (Form == dwarf::DW_FORM_data4)

325 return 4;

326

327 if (Form == dwarf::DW_FORM_data8)

328 return 8;

329

330 if (Form == dwarf::DW_FORM_data16)

331 return 16;

332

334}

335

339

342

343

344

353 }

354

356

357

358 if (!LineTable.Prologue.FileNames.empty()) {

359 Tasks.push_back(

361 }

362

363

365

366

369 Tasks.push_back([&]() -> Error {

372 });

373 }

374

375

377

378

380

382 Tasks, [&](std::function<Error(void)> F) { return F(); }))

383 return Err;

384

386}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

A structured debug information entry.

unsigned getAbbrevNumber() const

unsigned getOffset() const

Get the compile/type unit relative offset of this DIE.

void setOffset(unsigned O)

static LLVM_ABI DWARFFormValue createFromPValue(dwarf::Form F, const char *V)

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

StringRef str() const

Explicit conversion to StringRef.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

const ValueTy & getValue() const

const char * getKeyData() const

getKeyData - Return the start of the string data that is the key for this value.

Triple - Helper class for working with autoconf configuration names.

@ Pub

.debug_pubnames, .debug_pubtypes

This class is a helper to create output DIE tree.

std::pair< DIEValue &, size_t > addStringPlaceholderAttribute(dwarf::Attribute Attr, dwarf::Form AttrForm)

Adds string attribute with dummy offset to the current DIE.

DIE * createDIE(dwarf::Tag DieTag, uint32_t OutOffset)

Creates a DIE of specified tag DieTag and OutOffset.

std::pair< DIEValue &, size_t > addScalarAttribute(dwarf::Attribute Attr, dwarf::Form AttrForm, uint64_t Value)

Adds specified scalar attribute to the current DIE.

std::string UnitName

The name of this unit.

IndexedValuesMap< const StringEntry * > DebugStringIndexMap

Maps a string into the index inside .debug_str_offsets section.

unsigned ID

Unique ID for the unit.

StringRef getUnitName() const

Returns this unit name.

void setOutUnitDIE(DIE *UnitDie)

Set output unit DIE.

DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID, StringRef ClangModuleName)

DIE * getOutUnitDIE()

Returns output unit DIE.

This class keeps data and services common for the whole linking process.

const DWARFLinkerOptions & getOptions() const

Returns linking options.

uint16_t getDebugStrOffsetsHeaderSize() const

Return size of header of debug_str_offsets table.

LinkingGlobalData & GlobalData

dwarf::FormParams Format

Format for sections.

const dwarf::FormParams & getFormParams() const

Return size of address.

void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness)

Sets output format for all keeping sections.

uint16_t getVersion() const

Return DWARF version.

uint16_t getDebugInfoHeaderSize() const

Return size of header of debug_info table.

void forEach(function_ref< void(SectionDescriptor &)> Handler)

Enumerate all sections and call Handler for each.

SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)

Returns descriptor for the specified section of SectionKind.

Error finishCloningAndEmit(const Triple &TargetTriple)

Emits resulting dwarf based on information from DIE tree.

Definition DWARFLinkerTypeUnit.cpp:336

void createDIETree(BumpPtrAllocator &Allocator)

Generates DIE tree based on information from TypesMap.

Definition DWARFLinkerTypeUnit.cpp:41

TypeUnit(LinkingGlobalData &GlobalData, unsigned ID, std::optional< uint16_t > Language, dwarf::FormParams Format, llvm::endianness Endianess)

Definition DWARFLinkerTypeUnit.cpp:17

LLVM_ABI void spawn(std::function< void()> f)

Error emitDebugInfo(const Triple &TargetTriple)

Emit .debug_info section for unit DIEs.

Error emitDebugStringOffsetSection()

Emit the .debug_str_offsets section for current unit.

void emitPubAccelerators()

Emit .debug_pubnames and .debug_pubtypes for Unit.

Error emitAbbreviations()

Error emitDebugLine(const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable)

Emit .debug_line section.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

SmallVector< uint64_t * > OffsetsPtrVector

Type for list of pointers to patches offsets.

StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry

StringMapEntry< EmptyStringSetTag > StringEntry

StringEntry keeps data of the string: the length, external offset and a string body which is placed r...

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

LLVM_ABI unsigned getULEB128Size(uint64_t Value)

Utility function to get the size of the ULEB128-encoded value.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

BumpPtrAllocatorImpl<> BumpPtrAllocator

The standard BumpPtrAllocator which just uses the default template parameters.

Error parallelForEachError(RangeTy &&R, FuncTy Fn)

A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...

bool AllowNonDeterministicOutput

Allow to generate valid, but non deterministic output.

This structure is used to update strings offsets into .debug_str.

This structure is used to keep data of the concrete section.

void notePatchWithOffsetUpdate(const T &Patch, OffsetsPtrVector &PatchesOffsetsList)

While creating patches, offsets to attributes may be partially unknown(because size of abbreviation n...