LLVM: lib/MC/MCCodeView.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

24

25using namespace llvm;

27

29 if (!StrTabFragment)

30 return;

32 StrTabFragment->setVarContents(StrTab);

33}

34

35

36

38 unsigned Idx = FileNumber - 1;

39 if (Idx < Files.size())

40 return Files[Idx].Assigned;

41 return false;

42}

43

48 assert(FileNumber > 0);

50 Filename = FilenameOffset.first;

51 unsigned Idx = FileNumber - 1;

52 if (Idx >= Files.size())

53 Files.resize(Idx + 1);

54

55 if (Filename.empty())

56 Filename = "";

57

58 if (Files[Idx].Assigned)

59 return false;

60

62 Filename = FilenameOffset.first;

63 unsigned Offset = FilenameOffset.second;

64

65 auto ChecksumOffsetSymbol =

67 Files[Idx].StringTableOffset = Offset;

68 Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;

69 Files[Idx].Assigned = true;

70 Files[Idx].Checksum = ChecksumBytes;

71 Files[Idx].ChecksumKind = ChecksumKind;

72

73 return true;

74}

75

77 if (FuncId >= Functions.size())

78 return nullptr;

79 if (Functions[FuncId].isUnallocatedFunctionInfo())

80 return nullptr;

81 return &Functions[FuncId];

82}

83

85 if (FuncId >= Functions.size())

86 Functions.resize(FuncId + 1);

87

88

89 if (!Functions[FuncId].isUnallocatedFunctionInfo())

90 return false;

91

92

94 return true;

95}

96

98 unsigned IAFile, unsigned IALine,

99 unsigned IACol) {

100 if (FuncId >= Functions.size())

101 Functions.resize(FuncId + 1);

102

103

104 if (!Functions[FuncId].isUnallocatedFunctionInfo())

105 return false;

106

108 InlinedAt.File = IAFile;

109 InlinedAt.Line = IALine;

110 InlinedAt.Col = IACol;

111

112

115 Info->InlinedAt = InlinedAt;

116

117

118

119 while (Info->isInlinedCallSite()) {

120 InlinedAt = Info->InlinedAt;

122 Info->InlinedAtMap[FuncId] = InlinedAt;

123 }

124

125 return true;

126}

127

129 unsigned FunctionId, unsigned FileNo,

130 unsigned Line, unsigned Column,

131 bool PrologueEnd, bool IsStmt) {

133 Label, FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt});

134}

135

137 auto Insertion =

138 StringTable.insert(std::make_pair(S, unsigned(StrTab.size())));

139

140 std::pair<StringRef, unsigned> Ret =

141 std::make_pair(Insertion.first->first(), Insertion.first->second);

142 if (Insertion.second) {

143

144 StrTab.append(Ret.first.begin(), Ret.first.end() + 1);

145 }

146 return Ret;

147}

148

149unsigned CodeViewContext::getStringTableOffset(StringRef S) {

150

152 return 0;

155 return I->second;

156}

157

160 MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false),

161 *StringEnd = Ctx.createTempSymbol("strtab_end", false);

162

166

167

168

169

170 if (!StrTabFragment) {

174 }

175

177

179}

180

182

183

184 if (Files.empty())

185 return;

186

188 MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false),

189 *FileEnd = Ctx.createTempSymbol("filechecksums_end", false);

190

194

195 unsigned CurrentOffset = 0;

196

197

198

199

200 for (auto File : Files) {

203 CurrentOffset += 4;

204 if (!File.ChecksumKind) {

205 CurrentOffset +=

206 4;

207 } else {

208 CurrentOffset += 2;

209 CurrentOffset += File.Checksum.size();

210 CurrentOffset = alignTo(CurrentOffset, 4);

211 }

212

213 OS.emitInt32(File.StringTableOffset);

214

215 if (!File.ChecksumKind) {

216

217

219 continue;

220 }

222 OS.emitInt8(File.ChecksumKind);

225 }

226

228

229 ChecksumOffsetsAssigned = true;

230}

231

232

233

234

235

237 unsigned FileNo) {

238 unsigned Idx = FileNo - 1;

239

240 if (Idx >= Files.size())

241 Files.resize(Idx + 1);

242

243 if (ChecksumOffsetsAssigned) {

245 return;

246 }

247

250

252}

253

255 size_t Offset = MCCVLines.size();

256 auto I = MCCVLineStartStop.insert(

258 if (I.second)

259 I.first->second.second = Offset + 1;

260 MCCVLines.push_back(LineEntry);

261}

262

263std::vector

265 std::vector FilteredLines;

266 size_t LocBegin;

267 size_t LocEnd;

269 if (LocBegin >= LocEnd) {

270 return FilteredLines;

271 }

272

274 for (size_t Idx = LocBegin; Idx != LocEnd; ++Idx) {

275 unsigned LocationFuncId = MCCVLines[Idx].getFunctionId();

276 if (LocationFuncId == FuncId) {

277

278 FilteredLines.push_back(MCCVLines[Idx]);

279 } else {

280

281

282 auto I = SiteInfo->InlinedAtMap.find(LocationFuncId);

285

286

287

288 if (FilteredLines.empty() ||

289 FilteredLines.back().getFileNum() != IA.File ||

290 FilteredLines.back().getLine() != IA.Line ||

291 FilteredLines.back().getColumn() != IA.Col) {

292 FilteredLines.push_back(MCCVLoc(MCCVLines[Idx].getLabel(), FuncId,

293 IA.File, IA.Line, IA.Col, false,

294 false));

295 }

296 }

297 }

298 }

299 return FilteredLines;

300}

301

303 auto I = MCCVLineStartStop.find(FuncId);

304

305 if (I == MCCVLineStartStop.end())

306 return {~0ULL, 0};

307 return I->second;

308}

309

310std::pair<size_t, size_t>

312 size_t LocBegin;

313 size_t LocEnd;

314 std::tie(LocBegin, LocEnd) = getLineExtent(FuncId);

315

316

318 if (SiteInfo) {

320 unsigned ChildId = KV.first;

322 LocBegin = std::min(LocBegin, Extent.first);

323 LocEnd = std::max(LocEnd, Extent.second);

324 }

325 }

326

327 return {LocBegin, LocEnd};

328}

329

331 if (R <= L)

332 return {};

333 if (L >= MCCVLines.size())

334 return {};

335 return ArrayRef(&MCCVLines[L], R - L);

336}

337

339 unsigned FuncId,

343 MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false),

344 *LineEnd = Ctx.createTempSymbol("linetable_end", false);

345

351

352

354 bool HaveColumns = any_of(Locs, [](const MCCVLoc &LineEntry) {

355 return LineEntry.getColumn() != 0;

356 });

359

360 for (auto I = Locs.begin(), E = Locs.end(); I != E;) {

361

362 unsigned CurFileNum = I->getFileNum();

363 auto FileSegEnd =

364 std::find_if(I, E, [CurFileNum](const MCCVLoc &Loc) {

365 return Loc.getFileNum() != CurFileNum;

366 });

367 unsigned EntryCount = FileSegEnd - I;

369 Twine(StrTab[Files[CurFileNum - 1].StringTableOffset]) +

370 "' begins");

374 SegmentSize += 8 * EntryCount;

375 if (HaveColumns)

376 SegmentSize += 4 * EntryCount;

378

379 for (auto J = I; J != FileSegEnd; ++J) {

381 unsigned LineData = J->getLine();

382 if (J->isStmt())

385 }

386 if (HaveColumns) {

387 for (auto J = I; J != FileSegEnd; ++J) {

390 }

391 }

392 I = FileSegEnd;

393 }

395}

396

400 return true;

401 }

402

406 return true;

407 }

408

414 return true;

415 }

416

417 return false;

418}

419

424

426 if (Data >> 31)

427 return ((-Data) << 1) | 1;

428 return Data << 1;

429}

430

432 unsigned PrimaryFunctionId,

433 unsigned SourceFileId,

434 unsigned SourceLineNum,

437

438

440 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);

441}

442

445 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,

447

448

449 FixedSizePortion = MCCtx->allocateString(FixedSizePortion);

450 auto &Saved = DefRangeStorage.emplace_back(Ranges.begin(), Ranges.end());

451

452

454}

455

458 MCContext &Ctx = Asm.getContext();

461 const MCExpr *AddrDelta =

463 int64_t Result;

465 assert(Success && "failed to evaluate label difference as absolute");

467 assert(Result >= 0 && "negative label difference requested");

468 assert(Result < UINT_MAX && "label difference greater than 2GB");

470}

471

474 size_t LocBegin;

475 size_t LocEnd;

477

478 if (LocBegin >= LocEnd)

479 return;

481 if (Locs.empty())

482 return;

483

484

485#ifndef NDEBUG

486 const MCSection *FirstSec = &Locs.front().getLabel()->getSection();

488 if (&Loc.getLabel()->getSection() != FirstSec) {

489 errs() << ".cv_loc " << Loc.getFunctionId() << ' ' << Loc.getFileNum()

490 << ' ' << Loc.getLine() << ' ' << Loc.getColumn()

491 << " is in the wrong section\n";

493 }

494 }

495#endif

496

497

498

499

502 StartLoc.setFileNum(Frag.StartFileId);

503 StartLoc.setLine(Frag.StartLineNum);

504 bool HaveOpenRange = false;

505

508 LastSourceLoc.File = Frag.StartFileId;

509 LastSourceLoc.Line = Frag.StartLineNum;

510

512

515

516

517

518 constexpr uint32_t InlineSiteSize = 12;

519 constexpr uint32_t AnnotationSize = 8;

520 size_t MaxBufferSize = MaxRecordLength - InlineSiteSize - AnnotationSize;

521 if (Buffer.size() >= MaxBufferSize)

522 break;

523

524 if (Loc.getFunctionId() == Frag.SiteFuncId) {

525 CurSourceLoc.File = Loc.getFileNum();

526 CurSourceLoc.Line = Loc.getLine();

527 } else {

530

531

532

533 CurSourceLoc = I->second;

534 } else {

535

536

537 if (HaveOpenRange) {

541 LastLabel = Loc.getLabel();

542 }

543 HaveOpenRange = false;

544 continue;

545 }

546 }

547

548

549

550

551 if (HaveOpenRange && CurSourceLoc.File == LastSourceLoc.File &&

552 CurSourceLoc.Line == LastSourceLoc.Line)

553 continue;

554

555 HaveOpenRange = true;

556

557 if (CurSourceLoc.File != LastSourceLoc.File) {

558 unsigned FileOffset = static_cast<const MCConstantExpr *>(

559 Files[CurSourceLoc.File - 1]

560 .ChecksumTableOffset->getVariableValue())

564 }

565

566 int LineDelta = CurSourceLoc.Line - LastSourceLoc.Line;

569 if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) {

570

571

572

573 unsigned Operand = (EncodedLineDelta << 4) | CodeDelta;

575 Buffer);

577 } else {

578

579 if (LineDelta != 0) {

582 }

585 }

586

587 LastLabel = Loc.getLabel();

588 LastSourceLoc = CurSourceLoc;

589 }

590

591 assert(HaveOpenRange);

592

593 unsigned EndSymLength =

595 unsigned LocAfterLength = ~0U;

597 if (!LocAfter.empty()) {

598

600 if (&Loc.getLabel()->getSection() == &LastLabel->getSection())

602 }

603

607}

608

611 MCContext &Ctx = Asm.getContext();

615

616

618 const MCSymbol *LastLabel = nullptr;

619 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) {

620 unsigned GapSize =

623 GapAndRangeSizes.push_back({GapSize, RangeSize});

624 LastLabel = Range.second;

625 }

626

627

628 for (size_t I = 0, E = Frag.getRanges().size(); I != E;) {

629

630

632 unsigned RangeSize = GapAndRangeSizes[I].second;

633 size_t J = I + 1;

634 for (; J != E; ++J) {

635 unsigned GapAndRangeSize = GapAndRangeSizes[J].first + GapAndRangeSizes[J].second;

636 if (RangeSize + GapAndRangeSize > MaxDefRange)

637 break;

638 RangeSize += GapAndRangeSize;

639 }

640 unsigned NumGaps = J - I - 1;

641

643

644 unsigned Bias = 0;

645

646

647 do {

649

653

654

655

657

658

659 size_t RecordSize = FixedSizePortion.size() +

661

663

664 OS << FixedSizePortion;

665

666

668 LEWriter.write<uint32_t>(0);

669

671 LEWriter.write<uint16_t>(0);

672

674

675

676 Bias += Chunk;

677 RangeSize -= Chunk;

678 } while (RangeSize > 0);

679

680

682 "large ranges should not have gaps");

683 unsigned GapStartOffset = GapAndRangeSizes[I].second;

684 for (++I; I != J; ++I) {

685 unsigned GapSize, RangeSize;

687 std::tie(GapSize, RangeSize) = GapAndRangeSizes[I];

690 GapStartOffset += GapSize + RangeSize;

691 }

692 }

693

695 assert(Fixups.size() < 256 && "Store fixups outside of MCFragment's VarFixup "

696 "storage if the number ever exceeds 256");

698}

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

Fixup Statepoint Caller Saved

static unsigned computeLabelDiff(const MCAssembler &Asm, const MCSymbol *Begin, const MCSymbol *End)

Definition MCCodeView.cpp:456

static uint32_t encodeSignedNumber(uint32_t Data)

Definition MCCodeView.cpp:425

static bool compressAnnotation(uint32_t Data, SmallVectorImpl< char > &Buffer)

Definition MCCodeView.cpp:397

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

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

const T & front() const

front - Get the first element.

bool empty() const

empty - Check if the array is empty.

ArrayRef< MCCVLoc > getLinesForExtent(size_t L, size_t R)

Definition MCCodeView.cpp:330

std::pair< size_t, size_t > getLineExtent(unsigned FuncId)

Definition MCCodeView.cpp:302

void encodeInlineLineTable(const MCAssembler &Asm, MCCVInlineLineTableFragment &F)

Encodes the binary annotations once we have a layout.

Definition MCCodeView.cpp:472

void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId, const MCSymbol *FuncBegin, const MCSymbol *FuncEnd)

Emits a line table substream.

Definition MCCodeView.cpp:338

void emitFileChecksums(MCObjectStreamer &OS)

Emits the file checksum substream.

Definition MCCodeView.cpp:181

void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt)

Saves the information from the currently parsed .cv_loc directive and sets CVLocSeen.

Definition MCCodeView.cpp:128

void emitDefRange(MCObjectStreamer &OS, ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > Ranges, StringRef FixedSizePortion)

Definition MCCodeView.cpp:443

bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename, ArrayRef< uint8_t > ChecksumBytes, uint8_t ChecksumKind)

Definition MCCodeView.cpp:44

MCCVFunctionInfo * getCVFunctionInfo(unsigned FuncId)

Retreive the function info if this is a valid function id, or nullptr.

Definition MCCodeView.cpp:76

bool recordFunctionId(unsigned FuncId)

Records the function id of a normal function.

Definition MCCodeView.cpp:84

void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo)

Emits the offset into the checksum table of the given file number.

Definition MCCodeView.cpp:236

std::vector< MCCVLoc > getFunctionLineEntries(unsigned FuncId)

Definition MCCodeView.cpp:264

void addLineEntry(const MCCVLoc &LineEntry)

Add a line entry.

Definition MCCodeView.cpp:254

bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol)

Records the function id of an inlined call site.

Definition MCCodeView.cpp:97

std::pair< size_t, size_t > getLineExtentIncludingInlinees(unsigned FuncId)

Definition MCCodeView.cpp:311

void emitInlineLineTableForFunction(MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)

Definition MCCodeView.cpp:431

void finish()

Definition MCCodeView.cpp:28

void emitStringTable(MCObjectStreamer &OS)

Emits the string table substream.

Definition MCCodeView.cpp:158

bool isValidFileNumber(unsigned FileNumber) const

This is a valid number for use with .cv_loc if we've already seen a .cv_file for it.

Definition MCCodeView.cpp:37

void encodeDefRange(const MCAssembler &Asm, MCCVDefRangeFragment &F)

Definition MCCodeView.cpp:609

std::pair< StringRef, unsigned > addToStringTable(StringRef S)

Add something to the string table.

Definition MCCodeView.cpp:136

Binary assembler expressions.

static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())

static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())

Fragment representing the .cv_def_range directive.

ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > getRanges() const

StringRef getFixedSizePortion() const

Fragment representing the binary annotations produced by the .cv_inline_linetable directive.

const MCSymbol * getFnStartSym() const

const MCSymbol * getFnEndSym() const

Instances of this class represent the information from a .cv_loc directive.

void setFileNum(unsigned fileNum)

Set the FileNum of this MCCVLoc.

void setLabel(const MCSymbol *L)

unsigned getColumn() const

Get the Column of this MCCVLoc.

unsigned getFunctionId() const

void setLine(unsigned line)

Set the Line of this MCCVLoc.

static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Context object for machine code objects.

LLVM_ABI MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

Base class for the full range of assembler expressions which are needed for parsing.

LLVM_ABI bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const

Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.

static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)

Consider bit fields if we need more flags.

LLVM_ABI void setVarFixups(ArrayRef< MCFixup > Fixups)

LLVM_ABI void setVarContents(ArrayRef< char > Contents)

Streaming object file generation interface.

FT * newSpecialFragment(Args &&...args)

void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0) override

Emit some number of copies of Value until the byte alignment ByteAlignment is reached.

void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override

Emit an assignment of Value to Symbol.

void emitBytes(StringRef Data) override

Emit the bytes in Data into the output.

void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override

Emit a label for Symbol into the current section.

void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc()) override

Emit the expression Value into the output as a native integer of the given Size bytes.

void emitCVFileChecksumOffsetDirective(unsigned FileNo) override

This implements the CodeView '.cv_filechecksumoffset' assembler directive.

void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) override

Emit the absolute difference between two symbols if possible.

Instances of this class represent a uniqued identifier for a section in the current translation unit.

Streaming machine code generation interface.

MCFragment * getCurrentFragment() const

MCContext & getContext() const

virtual void AddComment(const Twine &T, bool EOL=true)

Add a textual comment.

virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)

Emits a COFF section relative relocation.

void emitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative=false)

Special case of EmitValue that avoids the client having to pass in a MCExpr for MCSymbols.

virtual void emitCOFFSectionIndex(MCSymbol const *Symbol)

Emits a COFF section index.

void emitInt16(uint64_t Value)

void emitInt32(uint64_t Value)

void emitInt8(uint64_t Value)

Represent a reference to a symbol from inside an expression.

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

MCSection & getSection() const

Get the section associated with a defined, non-absolute symbol.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

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 bool empty() const

empty - Check if the string is empty.

constexpr size_t size() const

size - Get the string size.

A table of densely packed, null-terminated strings indexed by offset.

constexpr Iterator end() const

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

A raw_ostream that writes to an SmallVector or SmallString.

This class represents a function that is read from a sample profile.

#define llvm_unreachable(msg)

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

@ ChangeCodeOffsetAndLineOffset

This is an optimization pass for GlobalISel generic memory operations.

bool any_of(R &&range, UnaryPredicate P)

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

constexpr bool isUInt(uint64_t x)

Checks if an unsigned integer fits into the given bit width.

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

@ FK_SecRel_2

A two-byte section relative fixup.

@ FK_SecRel_4

A four-byte section relative fixup.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

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

StringRef toStringRef(bool B)

Construct a string ref from a boolean.

This struct is a compact representation of a valid (non-zero power of two) alignment.

Information describing a function or inlined call site introduced by .cv_func_id or ....

unsigned ParentFuncIdPlusOne

If this represents an inlined call site, then ParentFuncIdPlusOne will be the parent function id plus...

DenseMap< unsigned, LineInfo > InlinedAtMap

Map from inlined call site id to the inlined at location to use for that call site.

Adapter to write values to a stream in a particular byte order.

void write(ArrayRef< value_type > Val)