LLVM: lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

31#include

32#include

33

34using namespace llvm;

38

39

41

43

45

46

47

48

49

50

52

54

57

60

61

62

63

66};

67

68

73 }

77 return Tombstone;

78 }

81 }

83 return LHS.RecordData == RHS.RecordData;

84 }

85};

86

87namespace {

89struct PublicSym32Layout {

92

93};

95}

96

97

100 NameLen = std::min(NameLen,

102 return alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);

103}

104

106

109 size_t Size = alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);

111 auto *FixedMem = reinterpret_cast<PublicSym32Layout *>(Mem);

112 FixedMem->Prefix.RecordKind = static_cast<uint16_t>(codeview::S_PUB32);

113 FixedMem->Prefix.RecordLen = static_cast<uint16_t>(Size - 2);

114 FixedMem->Pub.Flags = Pub.Flags;

115 FixedMem->Pub.Offset = Pub.Offset;

116 FixedMem->Pub.Segment = Pub.Segment;

117 char *NameMem = reinterpret_cast<char *>(FixedMem + 1);

118 memcpy(NameMem, Pub.Name, NameLen);

119

120 memset(&NameMem[NameLen], 0, Size - sizeof(PublicSym32Layout) - NameLen);

122}

123

130}

131

138

140 return EC;

141

143 return EC;

145 return EC;

147 return EC;

149}

150

153}

154

155

157 size_t LS = S1.size();

158 size_t RS = S2.size();

159

160 if (LS != RS)

161 return (LS > RS) - (LS < RS);

162

163

166

167

168 return S1.compare_insensitive(S2.data());

169}

170

171void GSIStreamBuilder::finalizePublicBuckets() {

172 PSH->finalizeBuckets(0, Publics);

173}

174

175void GSIStreamBuilder::finalizeGlobalBuckets(uint32_t RecordZeroOffset) {

176

177

178

179

180

181

182

183

184 std::vector Records;

185 Records.resize(Globals.size());

186 uint32_t SymOffset = RecordZeroOffset;

187 for (size_t I = 0, E = Globals.size(); I < E; ++I) {

191 Records[I].SymOffset = SymOffset;

192 SymOffset += Globals[I].length();

193 }

194

195 GSH->finalizeBuckets(RecordZeroOffset, Records);

196}

197

200

201 parallelFor(0, Records.size(), [&](size_t I) {

202 Records[I].setBucketIdx(hashStringV1(Records[I].Name) % IPHR_HASH);

203 });

204

205

206

207

210 ++BucketStarts[P.BucketIdx];

212 for (uint32_t &B : BucketStarts) {

214 B = Sum;

216 }

217

218

219

220

223 memcpy(BucketCursors, BucketStarts, sizeof(BucketCursors));

224 for (int I = 0, E = Records.size(); I < E; ++I) {

225 uint32_t HashIdx = BucketCursors[Records[I].BucketIdx]++;

228 }

229

230

231

232

233

234

235

238 auto E = HashRecords.begin() + BucketCursors[I];

239 if (B == E)

240 return;

241 auto BucketCmp = [Records](const PSHashRecord &LHash,

245 assert(L.BucketIdx == R.BucketIdx);

246 int Cmp = gsiRecordCmp(L.getName(), R.getName());

247 if (Cmp != 0)

248 return Cmp < 0;

249

250

251

252 return L.SymOffset < R.SymOffset;

253 };

255

256

257

258

260 HRec.Off = Records[uint32_t(HRec.Off)].SymOffset + 1;

261 });

262

263

264

267 for (uint32_t J = 0; J < 32; ++J) {

268

271 BucketStarts[BucketIdx] == BucketCursors[BucketIdx])

272 continue;

273 Word |= (1U << J);

274

275

276

277

278 const int SizeOfHROffsetCalc = 12;

279 ulittle32_t ChainStartOff =

280 ulittle32_t(BucketStarts[BucketIdx] * SizeOfHROffsetCalc);

282 }

284 }

285}

286

290

292

293uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize() const {

296 Size += PSH->calculateSerializedLength();

297 Size += Publics.size() * sizeof(uint32_t);

298

299

301}

302

303uint32_t GSIStreamBuilder::calculateGlobalsHashStreamSize() const {

304 return GSH->calculateSerializedLength();

305}

306

308

309 finalizePublicBuckets();

310 finalizeGlobalBuckets(PSH->RecordByteSize);

311

313 if (Idx)

314 return Idx.takeError();

315 GlobalsStreamIndex = *Idx;

316

317 Idx = Msf.addStream(calculatePublicsHashStreamSize());

318 if (Idx)

319 return Idx.takeError();

320 PublicsStreamIndex = *Idx;

321

322 uint32_t RecordBytes = PSH->RecordByteSize + GSH->RecordByteSize;

323

325 if (Idx)

326 return Idx.takeError();

327 RecordStreamIndex = *Idx;

329}

330

332 assert(Publics.empty() && PSH->RecordByteSize == 0 &&

333 "publics can only be added once");

334 Publics = std::move(PublicsIn);

335

336

338 return L.getName() < R.getName();

339 });

340

341

344 Pub.SymOffset = SymOffset;

346 }

347

348

349 PSH->RecordByteSize = SymOffset;

350}

351

353 serializeAndAddGlobal(Sym);

354}

355

357 serializeAndAddGlobal(Sym);

358}

359

361 serializeAndAddGlobal(Sym);

362}

363

364template

365void GSIStreamBuilder::serializeAndAddGlobal(const T &Symbol) {

368 CodeViewContainer::Pdb));

369}

370

372

373 if (Symbol.kind() == S_UDT || Symbol.kind() == S_CONSTANT) {

374 auto Iter = GlobalsSeen.insert(Symbol);

375 if (!Iter.second)

376 return;

377 }

378 GSH->RecordByteSize += Symbol.length();

379 Globals.push_back(Symbol);

380}

381

382

385 std::vector<uint8_t> Storage;

386 for (const BulkPublic &Pub : Publics) {

390 return E;

391 }

393}

394

398 ItemStream.setItems(Records);

401}

402

403Error GSIStreamBuilder::commitSymbolRecordStream(

406

407

408

409

411 return EC;

413 return EC;

414

416}

417

418static std::vectorsupport::ulittle32\_t

420

421

422 std::vector<ulittle32_t> PubAddrMap;

423 PubAddrMap.reserve(Publics.size());

424 for (int I = 0, E = Publics.size(); I < E; ++I)

425 PubAddrMap.push_back(ulittle32_t(I));

426

427 auto AddrCmp = [Publics](const ulittle32_t &LIdx, const ulittle32_t &RIdx) {

430 if (L.Segment != R.Segment)

431 return L.Segment < R.Segment;

432 if (L.Offset != R.Offset)

433 return L.Offset < R.Offset;

434

435

436 return L.getName() < R.getName();

437 };

439

440

441 for (ulittle32_t &Entry : PubAddrMap)

442 Entry = Publics[Entry].SymOffset;

443 return PubAddrMap;

444}

445

446Error GSIStreamBuilder::commitPublicsHashStream(

450

451

452 Header.SymHash = PSH->calculateSerializedLength();

453 Header.AddrMap = Publics.size() * 4;

454 Header.NumThunks = 0;

455 Header.SizeOfThunk = 0;

456 Header.ISectThunkTable = 0;

457 memset(Header.Padding, 0, sizeof(Header.Padding));

458 Header.OffThunkTable = 0;

459 Header.NumSections = 0;

460 if (auto EC = Writer.writeObject(Header))

461 return EC;

462

463 if (auto EC = PSH->commit(Writer))

464 return EC;

465

466 std::vectorsupport::ulittle32\_t PubAddrMap = computeAddrMap(Publics);

467 assert(PubAddrMap.size() == Publics.size());

468 if (auto EC = Writer.writeArray(ArrayRef(PubAddrMap)))

469 return EC;

470

472}

473

474Error GSIStreamBuilder::commitGlobalsHashStream(

477 return GSH->commit(Writer);

478}

479

489

490 if (auto EC = commitSymbolRecordStream(*PRS))

491 return EC;

492 if (auto EC = commitGlobalsHashStream(*GS))

493 return EC;

494 if (auto EC = commitPublicsHashStream(*PS))

495 return EC;

497}

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define LLVM_UNLIKELY(EXPR)

#define LLVM_PACKED_START

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

static CVSymbol serializePublic(uint8_t *Mem, const BulkPublic &Pub)

static Error writePublics(BinaryStreamWriter &Writer, ArrayRef< BulkPublic > Publics)

static bool isAsciiString(StringRef S)

static Error writeRecords(BinaryStreamWriter &Writer, ArrayRef< CVSymbol > Records)

static int gsiRecordCmp(StringRef S1, StringRef S2)

static std::vector< support::ulittle32_t > computeAddrMap(ArrayRef< BulkPublic > Publics)

static uint32_t sizeOfPublic(const BulkPublic &Pub)

Merge contiguous icmps into a memcmp

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

BinaryItemStream represents a sequence of objects stored in some kind of external container but for w...

void setItems(ArrayRef< T > ItemArray)

BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.

Provides write only access to a subclass of WritableBinaryStream.

Error writeArray(ArrayRef< T > Array)

Writes an array of objects of type T to the underlying stream, as if by using memcpy.

Error writeStreamRef(BinaryStreamRef Ref)

Efficiently reads all data from Ref, and writes it to this stream.

Error writeBytes(ArrayRef< uint8_t > Buffer)

Write the bytes specified in Buffer to the underlying stream.

Error writeObject(const T &Obj)

Writes the object Obj to the underlying stream, as if by using memcpy.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

StringRef - Represent a constant reference to a string, i.e.

constexpr size_t size() const

size - Get the string size.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.

CVRecord is a fat pointer (base + size pair) to a symbol or type record.

ArrayRef< uint8_t > RecordData

static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, CodeViewContainer Container)

BumpPtrAllocator & getAllocator()

Expected< uint32_t > addStream(uint32_t Size, ArrayRef< uint32_t > Blocks)

Add a stream to the MSF file with the given size, occupying the given list of blocks.

static std::unique_ptr< WritableMappedBlockStream > createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, uint32_t StreamIndex, BumpPtrAllocator &Allocator)

void addPublicSymbols(std::vector< BulkPublic > &&PublicsIn)

Error finalizeMsfLayout()

uint32_t getRecordStreamIndex() const

Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer)

GSIStreamBuilder(msf::MSFBuilder &Msf)

void addGlobalSymbol(const codeview::ProcRefSym &Sym)

uint32_t getPublicsStreamIndex() const

uint32_t getGlobalsStreamIndex() const

@ C

The default llvm calling convention, compatible with C.

llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records

CVRecord< SymbolKind > CVSymbol

StringRef getSymbolName(CVSymbol Sym)

detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

uint64_t xxh3_64bits(ArrayRef< uint8_t > data)

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

void parallelSort(RandomAccessIterator Start, RandomAccessIterator End, const Comparator &Comp=Comparator())

void sort(IteratorTy Start, IteratorTy End)

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

void parallelFor(size_t Begin, size_t End, function_ref< void(size_t)> Fn)

Implement std::hash so that hash_code can be used in STL containers.

An information struct used to provide DenseMap with the various necessary components for a given valu...

This struct is equivalent to codeview::PublicSym32, but it has been optimized for size to speed up bu...

uint32_t calculateSerializedLength() const

std::vector< support::ulittle32_t > HashBuckets

void finalizePublicBuckets()

Error commit(BinaryStreamWriter &Writer)

std::array< support::ulittle32_t,(IPHR_HASH+32)/32 > HashBitmap

void finalizeGlobalBuckets(uint32_t RecordZeroOffset)

std::vector< PSHashRecord > HashRecords

void finalizeBuckets(uint32_t RecordZeroOffset, MutableArrayRef< BulkPublic > Globals)

static unsigned getHashValue(const CVSymbol &Val)

static CVSymbol getEmptyKey()

static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS)

static CVSymbol getTombstoneKey()