LLVM: lib/DebugInfo/CodeView/TypeRecordMapping.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

10

25

26#include

27#include

28#include

29#include

30#include

31

32using namespace llvm;

34

35namespace {

36

37#define error(X) \

38 do { \

39 if (auto EC = X) \

40 return EC; \

41 } while (false)

42

44#define CV_TYPE(enum, val) {#enum, enum},

45#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"

46};

47

49 switch (LT) {

50#define TYPE_RECORD(ename, value, name) \

51 case ename: \

52 return #name;

53#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"

54 default:

55 break;

56 }

57 return "UnknownLeaf";

58}

59

60template

63}

64

65template <typename T, typename TFlag>

69 return std::string("");

72 FlagVector SetFlags;

73 for (const auto &Flag : Flags) {

74 if (Flag.Value == 0)

75 continue;

77 SetFlags.push_back(Flag);

78 }

79 }

80

81 llvm::sort(SetFlags, &compEnumNames);

82

83 std::string FlagLabel;

84 bool FirstOcc = true;

85 for (const auto &Flag : SetFlags) {

86 if (FirstOcc)

87 FirstOcc = false;

88 else

89 FlagLabel += (" | ");

90

91 FlagLabel += (Flag.Name.str() + " (0x" + utohexstr(Flag.Value) + ")");

92 }

93

94 if (!FlagLabel.empty()) {

95 std::string LabelWithBraces(" ( ");

96 LabelWithBraces += FlagLabel + " )";

97 return LabelWithBraces;

98 } else

99 return FlagLabel;

100}

101

102template <typename T, typename TEnum>

106 return "";

108 for (const auto &EnumItem : EnumValues) {

109 if (EnumItem.Value == Value) {

110 Name = EnumItem.Name;

111 break;

112 }

113 }

114

116}

117

122 return "";

123 std::string AccessSpecifier = std::string(

125 std::string MemberAttrs(AccessSpecifier);

127 std::string MethodKind = std::string(

130 }

135 }

136 return MemberAttrs;

137}

138

139struct MapOneMethodRecord {

140 explicit MapOneMethodRecord(bool IsFromOverloadList)

141 : IsFromOverloadList(IsFromOverloadList) {}

142

143 Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {

144 std::string Attrs = getMemberAttributes(

145 IO, Method.getAccess(), Method.getMethodKind(), Method.getOptions());

147 if (IsFromOverloadList) {

150 }

152 if (Method.isIntroducingVirtual()) {

155 Method.VFTableOffset = -1;

156

157 if (!IsFromOverloadList)

159

161 }

162

163private:

164 bool IsFromOverloadList;

165};

166}

167

168

169

175 Hash.final(Result);

177}

178

182

183

184

187 size_t BytesNeeded = Name.size() + UniqueName.size() + 2;

188 if (BytesNeeded > BytesLeft) {

189

190 assert(BytesLeft >= 70);

191

192

195 std::string UniqueB = Twine("??@" + Hash + "@").str();

196 assert(UniqueB.size() == 36);

197

198

199

200 const size_t MaxTakeN = 4096;

201 size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;

203 std::string NameB = (Name.take_front(TakeN) + Hash).str();

204

209 } else {

212 }

213 } else {

214

215

218 }

219 } else {

220

221

222

226 }

227

229}

230

232 assert(!TypeKind && "Already in a type mapping!");

233 assert(!MemberKind && "Already in a member mapping!");

234

235

236

237

238 std::optional<uint32_t> MaxLen;

239 if (CVR.kind() != TypeLeafKind::LF_FIELDLIST &&

240 CVR.kind() != TypeLeafKind::LF_METHODLIST)

242 error(IO.beginRecord(MaxLen));

243 TypeKind = CVR.kind();

244

245 if (IO.isStreaming()) {

246 auto RecordKind = CVR.kind();

248 std::string RecordKindName = std::string(

250 error(IO.mapInteger(RecordLen, "Record length"));

251 error(IO.mapEnum(RecordKind, "Record kind: " + RecordKindName));

252 }

254}

255

257 if (IO.isStreaming())

259 utohexstr(Index.getIndex()) + ")");

261}

262

264 assert(TypeKind && "Not in a type mapping!");

265 assert(!MemberKind && "Still in a member mapping!");

266

267 error(IO.endRecord());

268

269 TypeKind.reset();

271}

272

274 assert(TypeKind && "Not in a type mapping!");

275 assert(!MemberKind && "Already in a member mapping!");

276

277

278

279

280

281

285

286 MemberKind = Record.Kind;

287 if (IO.isStreaming()) {

289 MemberKindName +=

290 " ( " +

292 .str() +

293 " )";

294 error(IO.mapEnum(Record.Kind, "Member kind: " + MemberKindName));

295 }

297}

298

300 assert(TypeKind && "Not in a type mapping!");

301 assert(MemberKind && "Not in a member mapping!");

302

303 if (IO.isReading()) {

304 if (auto EC = IO.skipPadding())

305 return EC;

306 }

307

308 MemberKind.reset();

309 error(IO.endRecord());

311}

312

314 std::string ModifierNames =

315 getFlagNames(IO, static_cast<uint16_t>(Record.Modifiers),

320}

321

322Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

324 std::string CallingConvName = std::string(getEnumName(

326 std::string FuncOptionNames =

327 getFlagNames(IO, static_cast<uint16_t>(Record.Options),

330 error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));

331 error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));

334

336}

337

338Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

340 std::string CallingConvName = std::string(getEnumName(

342 std::string FuncOptionNames =

343 getFlagNames(IO, static_cast<uint16_t>(Record.Options),

348 error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));

349 error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));

353

355}

356

358 error(IO.mapVectorN<uint32_t>(

360 [](CodeViewRecordIO &IO, TypeIndex &N) {

361 return IO.mapInteger(N, "Argument");

362 },

363 "NumArgs"));

365}

366

367Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

369 error(IO.mapVectorN<uint32_t>(

371 [](CodeViewRecordIO &IO, TypeIndex &N) {

372 return IO.mapInteger(N, "Strings");

373 },

374 "NumStrings"));

375

377}

378

380

381 SmallString<128> Attr("Attrs: ");

382

383 if (IO.isStreaming()) {

384 std::string PtrType = std::string(getEnumName(

386 Attr += "[ Type: " + PtrType;

387

388 std::string PtrMode = std::string(getEnumName(

390 Attr += ", Mode: " + PtrMode;

391

392 auto PtrSizeOf = Record.getSize();

393 Attr += ", SizeOf: " + itostr(PtrSizeOf);

394

396 Attr += ", isFlat";

398 Attr += ", isConst";

400 Attr += ", isVolatile";

402 Attr += ", isUnaligned";

404 Attr += ", isRestricted";

406 Attr += ", isThisPtr&";

408 Attr += ", isThisPtr&&";

409 Attr += " ]";

410 }

411

413 error(IO.mapInteger(Record.Attrs, Attr));

414

416 if (IO.isReading())

418

419 MemberPointerInfo &M = *Record.MemberInfo;

420 error(IO.mapInteger(M.ContainingType, "ClassType"));

421 std::string PtrMemberGetRepresentation = std::string(getEnumName(

423 error(IO.mapEnum(M.Representation,

424 "Representation: " + PtrMemberGetRepresentation));

425 }

426

428}

429

433 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));

434 error(IO.mapStringZ(Record.Name, "Name"));

435

437}

438

440 assert((CVR.kind() == TypeLeafKind::LF_STRUCTURE) ||

441 (CVR.kind() == TypeLeafKind::LF_CLASS) ||

442 (CVR.kind() == TypeLeafKind::LF_INTERFACE));

443

444 std::string PropertiesNames =

445 getFlagNames(IO, static_cast<uint16_t>(Record.Options),

448 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));

452 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));

455

457}

458

460 std::string PropertiesNames =

461 getFlagNames(IO, static_cast<uint16_t>(Record.Options),

464 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));

466 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));

469

471}

472

474 std::string PropertiesNames =

475 getFlagNames(IO, static_cast<uint16_t>(Record.Options),

478 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));

480 error(IO.mapInteger(Record.FieldList, "FieldListType"));

483

485}

486

488 error(IO.mapInteger(Record.Type, "Type"));

489 error(IO.mapInteger(Record.BitSize, "BitSize"));

491

493}

494

495Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

497 uint16_t Size;

498 if (!IO.isReading()) {

499 ArrayRef Slots = Record.getSlots();

501 error(IO.mapInteger(Size, "VFEntryCount"));

502

503 for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {

504 uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;

505 if ((SlotIndex + 1) < Slots.size()) {

506 Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);

507 }

509 }

510 } else {

512 for (uint16_t I = 0; I < Size; I += 2) {

513 uint8_t Byte;

516 if ((I + 1) < Size)

518 }

519 }

520

522}

523

528 uint32_t NamesLen = 0;

529 if (!IO.isReading()) {

531 NamesLen += Name.size() + 1;

532 }

533 error(IO.mapInteger(NamesLen));

534 error(IO.mapVectorTail(

536 [](CodeViewRecordIO &IO, StringRef &S) {

537 return IO.mapStringZ(S, "MethodName");

538 },

539 "VFTableName"));

540

542}

543

545 error(IO.mapInteger(Record.Id, "Id"));

546 error(IO.mapStringZ(Record.String, "StringData"));

547

549}

550

551Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

553 error(IO.mapInteger(Record.UDT, "UDT"));

556

558}

559

560Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

562 error(IO.mapInteger(Record.UDT, "UDT"));

565 error(IO.mapInteger(Record.Module, "Module"));

566

568}

569

573 error(IO.mapStringZ(Record.Name, "Name"));

574

576}

577

578Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

582 error(IO.mapStringZ(Record.Name, "Name"));

583

585}

586

587Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

589 error(IO.mapVectorN<uint16_t>(

591 [](CodeViewRecordIO &IO, TypeIndex &N) {

592 return IO.mapInteger(N, "Argument");

593 },

594 "NumArgs"));

595

597}

598

599Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

601

602

603 error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true), "Method"));

604

606}

607

608Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

610 if (IO.isStreaming()) {

612 return EC;

613 } else

614 error(IO.mapByteVectorTail(Record.Data));

615

617}

618

619Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

621 error(IO.mapGuid(Record.Guid, "Guid"));

622 error(IO.mapInteger(Record.Age, "Age"));

623 error(IO.mapStringZ(Record.Name, "Name"));

625}

626

628 std::string ModeName = std::string(

630 error(IO.mapEnum(Record.Mode, "Mode: " + ModeName));

632}

633

636 std::string Attrs = getMemberAttributes(

638 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));

639 error(IO.mapInteger(Record.Type, "BaseType"));

640 error(IO.mapEncodedInteger(Record.Offset, "BaseOffset"));

641

643}

644

647 std::string Attrs = getMemberAttributes(

649 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));

650

651

652 error(IO.mapEncodedInteger(Record.Value, "EnumValue"));

653 error(IO.mapStringZ(Record.Name, "Name"));

654

656}

657

660 std::string Attrs = getMemberAttributes(

662 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));

663 error(IO.mapInteger(Record.Type, "Type"));

664 error(IO.mapEncodedInteger(Record.FieldOffset, "FieldOffset"));

665 error(IO.mapStringZ(Record.Name, "Name"));

666

668}

669

673 error(IO.mapInteger(Record.MethodList, "MethodListIndex"));

674 error(IO.mapStringZ(Record.Name, "Name"));

675

677}

678

681 const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);

682 MapOneMethodRecord Mapper(IsFromOverloadList);

683 return Mapper(IO, Record);

684}

685

689 error(IO.mapInteger(Padding, "Padding"));

690 error(IO.mapInteger(Record.Type, "Type"));

691 error(IO.mapStringZ(Record.Name, "Name"));

692

694}

695

698

699 std::string Attrs = getMemberAttributes(

701 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));

702 error(IO.mapInteger(Record.Type, "Type"));

703 error(IO.mapStringZ(Record.Name, "Name"));

704

706}

707

710

711 std::string Attrs = getMemberAttributes(

713 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));

714 error(IO.mapInteger(Record.BaseType, "BaseType"));

716 error(IO.mapEncodedInteger(Record.VBPtrOffset, "VBPtrOffset"));

717 error(IO.mapEncodedInteger(Record.VTableIndex, "VBTableIndex"));

718

720}

721

725 error(IO.mapInteger(Padding, "Padding"));

726 error(IO.mapInteger(Record.Type, "Type"));

727

729}

730

734 error(IO.mapInteger(Padding, "Padding"));

736

738}

739

740Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

744 error(IO.mapInteger(Precomp.Signature, "Signature"));

747}

748

749Error TypeRecordMapping::visitKnownRecord(CVType &CVR,

751 error(IO.mapInteger(EndPrecomp.Signature, "Signature"));

753}

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

static constexpr uint32_t ContinuationLength

This file defines the SmallString class.

This file defines the SmallVector class.

static StringRef getLeafTypeName(TypeLeafKind LT)

static const EnumEntry< TypeLeafKind > LeafTypeNames[]

static void computeHashString(StringRef Name, SmallString< 32 > &StringifiedHash)

Definition TypeRecordMapping.cpp:170

#define error(X)

Definition TypeRecordMapping.cpp:37

static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName)

Definition TypeRecordMapping.cpp:179

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

size_t size() const

size - Get the array size.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

LLVM_ABI void update(ArrayRef< uint8_t > Data)

Updates the hash for the byte stream provided.

static LLVM_ABI void stringifyResult(MD5Result &Result, SmallVectorImpl< char > &Str)

Translates the bytes in Res to a hex string that is deposited into Str.

LLVM_ABI void final(MD5Result &Result)

Finishes off the hash and puts the result in result.

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

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

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

constexpr size_t size() const

size - Get the string size.

StringRef take_front(size_t N=1) const

Return a StringRef equal to 'this' but with only the first N elements remaining.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

LLVM_ABI std::string str() const

Return the twine contents as a std::string.

LLVM Value Representation.

std::vector< TypeIndex > ArgIndices

MemberAccess getAccess() const

SmallVector< TypeIndex, MaxArgs > ArgIndices

LLVM_ABI Error mapInteger(TypeIndex &TypeInd, const Twine &Comment="")

LLVM_ABI Error mapStringZ(StringRef &Value, const Twine &Comment="")

Error mapEnum(T &Value, const Twine &Comment="")

LLVM_ABI uint32_t maxFieldLength() const

MemberAccess getAccess() const

MemberAccess getAccess() const

LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.

TypeIndex ContinuationIndex

std::vector< OneMethodRecord > Methods

For method overload sets. LF_METHOD.

bool isRValueReferenceThisPtr() const

std::optional< MemberPointerInfo > MemberInfo

bool isPointerToMember() const

bool isLValueReferenceThisPtr() const

PointerMode getMode() const

PointerKind getPointerKind() const

StringRef PrecompFilePath

MemberAccess getAccess() const

std::vector< TypeIndex > StringIndices

bool hasUniqueName() const

Error visitTypeBegin(CVType &Record) override

Paired begin/end actions for all types.

Definition TypeRecordMapping.cpp:231

Error visitMemberBegin(CVMemberRecord &Record) override

Definition TypeRecordMapping.cpp:273

Error visitTypeEnd(CVType &Record) override

Definition TypeRecordMapping.cpp:263

Error visitMemberEnd(CVMemberRecord &Record) override

Definition TypeRecordMapping.cpp:299

TypeIndex OverriddenVFTable

std::vector< StringRef > MethodNames

ArrayRef< VFTableSlotKind > getSlots() const

std::vector< VFTableSlotKind > Slots

MemberAccess getAccess() const

constexpr char Attrs[]

Key for Kernel::Metadata::mAttrs.

Flag

These should be considered private to the implementation of the MCInstrDesc class.

LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getMethodOptionNames()

MethodKind

Part of member attribute flags. (CV_methodprop_e)

LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getCallingConventions()

LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getMemberAccessNames()

CVRecord< TypeLeafKind > CVType

LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getPtrKindNames()

LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getPtrMemberRepNames()

LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getLabelTypeEnum()

LLVM_ABI Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)

LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getTypeModifierNames()

MethodOptions

Equivalent to CV_fldattr_t bitfield.

LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getMemberKindNames()

MemberAccess

Source-level access specifier. (CV_access_e)

TypeLeafKind

Duplicate copy of the above enum, but using the official CV names.

LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getPtrModeNames()

LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getFunctionOptionEnum()

LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getClassOptionNames()

This is an optimization pass for GlobalISel generic memory operations.

std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)

void sort(IteratorTy Start, IteratorTy End)

ArrayRef(const T &OneElt) -> ArrayRef< T >

std::string itostr(int64_t X)