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)

31}

32

33

34

36 unsigned Idx = FileNumber - 1;

38 return Files[Idx].Assigned;

39 return false;

40}

41

46 assert(FileNumber > 0);

48 Filename = FilenameOffset.first;

49 unsigned Idx = FileNumber - 1;

52

53 if (Filename.empty())

54 Filename = "";

55

56 if (Files[Idx].Assigned)

57 return false;

58

60 Filename = FilenameOffset.first;

61 unsigned Offset = FilenameOffset.second;

62

63 auto ChecksumOffsetSymbol =

64 OS.getContext().createTempSymbol("checksum_offset", false);

65 Files[Idx].StringTableOffset = Offset;

66 Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;

67 Files[Idx].Assigned = true;

68 Files[Idx].Checksum = ChecksumBytes;

69 Files[Idx].ChecksumKind = ChecksumKind;

70

71 return true;

72}

73

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

76 return nullptr;

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

78 return nullptr;

79 return &Functions[FuncId];

80}

81

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

84 Functions.resize(FuncId + 1);

85

86

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

88 return false;

89

90

92 return true;

93}

94

96 unsigned IAFile, unsigned IALine,

97 unsigned IACol) {

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

99 Functions.resize(FuncId + 1);

100

101

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

103 return false;

104

106 InlinedAt.File = IAFile;

107 InlinedAt.Line = IALine;

108 InlinedAt.Col = IACol;

109

110

112 Info->ParentFuncIdPlusOne = IAFunc + 1;

113 Info->InlinedAt = InlinedAt;

114

115

116

117 while (Info->isInlinedCallSite()) {

118 InlinedAt = Info->InlinedAt;

120 Info->InlinedAtMap[FuncId] = InlinedAt;

121 }

122

123 return true;

124}

125

127 unsigned FunctionId, unsigned FileNo,

128 unsigned Line, unsigned Column,

129 bool PrologueEnd, bool IsStmt) {

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

132}

133

135 auto Insertion =

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

137

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

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

140 if (Insertion.second) {

141

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

143 }

144 return Ret;

145}

146

147unsigned CodeViewContext::getStringTableOffset(StringRef S) {

148

150 return 0;

153 return I->second;

154}

155

160

161 OS.emitInt32(uint32_t(DebugSubsectionKind::StringTable));

162 OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4);

163 OS.emitLabel(StringBegin);

164

165

166

167

168 if (!StrTabFragment) {

170 OS.insert(StrTabFragment);

171 }

172

173 OS.emitValueToAlignment(Align(4), 0);

174

175 OS.emitLabel(StringEnd);

176}

177

179

180

181 if (Files.empty())

182 return;

183

187

188 OS.emitInt32(uint32_t(DebugSubsectionKind::FileChecksums));

189 OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);

190 OS.emitLabel(FileBegin);

191

192 unsigned CurrentOffset = 0;

193

194

195

196

197 for (auto File : Files) {

198 OS.emitAssignment(File.ChecksumTableOffset,

200 CurrentOffset += 4;

201 if (!File.ChecksumKind) {

202 CurrentOffset +=

203 4;

204 } else {

205 CurrentOffset += 2;

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

207 CurrentOffset = alignTo(CurrentOffset, 4);

208 }

209

210 OS.emitInt32(File.StringTableOffset);

211

212 if (!File.ChecksumKind) {

213

214

215 OS.emitInt32(0);

216 continue;

217 }

218 OS.emitInt8(static_cast<uint8_t>(File.Checksum.size()));

219 OS.emitInt8(File.ChecksumKind);

220 OS.emitBytes(toStringRef(File.Checksum));

221 OS.emitValueToAlignment(Align(4));

222 }

223

224 OS.emitLabel(FileEnd);

225

226 ChecksumOffsetsAssigned = true;

227}

228

229

230

231

232

234 unsigned FileNo) {

235 unsigned Idx = FileNo - 1;

236

239

240 if (ChecksumOffsetsAssigned) {

241 OS.emitSymbolValue(Files[Idx].ChecksumTableOffset, 4);

242 return;

243 }

244

247

248 OS.emitValueImpl(SRE, 4);

249}

250

252 size_t Offset = MCCVLines.size();

253 auto I = MCCVLineStartStop.insert(

255 if (I.second)

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

257 MCCVLines.push_back(LineEntry);

258}

259

260std::vector

262 std::vector FilteredLines;

263 size_t LocBegin;

264 size_t LocEnd;

266 if (LocBegin >= LocEnd) {

267 return FilteredLines;

268 }

269

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

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

273 if (LocationFuncId == FuncId) {

274

275 FilteredLines.push_back(MCCVLines[Idx]);

276 } else {

277

278

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

282

283

284

285 if (FilteredLines.empty() ||

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

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

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

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

290 IA.File, IA.Line, IA.Col, false,

291 false));

292 }

293 }

294 }

295 }

296 return FilteredLines;

297}

298

300 auto I = MCCVLineStartStop.find(FuncId);

301

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

303 return {~0ULL, 0};

304 return I->second;

305}

306

307std::pair<size_t, size_t>

309 size_t LocBegin;

310 size_t LocEnd;

312

313

315 if (SiteInfo) {

317 unsigned ChildId = KV.first;

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

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

321 }

322 }

323

324 return {LocBegin, LocEnd};

325}

326

328 if (R <= L)

329 return {};

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

331 return {};

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

333}

334

342

343 OS.emitInt32(uint32_t(DebugSubsectionKind::Lines));

344 OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);

345 OS.emitLabel(LineBegin);

346 OS.emitCOFFSecRel32(FuncBegin, 0);

347 OS.emitCOFFSectionIndex(FuncBegin);

348

349

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

352 return LineEntry.getColumn() != 0;

353 });

355 OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4);

356

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

358

359 unsigned CurFileNum = I->getFileNum();

360 auto FileSegEnd =

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

362 return Loc.getFileNum() != CurFileNum;

363 });

364 unsigned EntryCount = FileSegEnd - I;

365 OS.AddComment("Segment for file '" +

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

367 "' begins");

368 OS.emitCVFileChecksumOffsetDirective(CurFileNum);

369 OS.emitInt32(EntryCount);

371 SegmentSize += 8 * EntryCount;

372 if (HaveColumns)

373 SegmentSize += 4 * EntryCount;

374 OS.emitInt32(SegmentSize);

375

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

377 OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4);

378 unsigned LineData = J->getLine();

379 if (J->isStmt())

380 LineData |= LineInfo::StatementFlag;

381 OS.emitInt32(LineData);

382 }

383 if (HaveColumns) {

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

385 OS.emitInt16(J->getColumn());

386 OS.emitInt16(0);

387 }

388 }

389 I = FileSegEnd;

390 }

391 OS.emitLabel(LineEnd);

392}

393

395 if (isUInt<7>(Data)) {

397 return true;

398 }

399

400 if (isUInt<14>(Data)) {

403 return true;

404 }

405

406 if (isUInt<29>(Data)) {

411 return true;

412 }

413

414 return false;

415}

416

420}

421

423 if (Data >> 31)

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

425 return Data << 1;

426}

427

429 unsigned PrimaryFunctionId,

430 unsigned SourceFileId,

431 unsigned SourceLineNum,

434

435

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

438 OS.insert(F);

439}

440

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

445

446

447 auto *F =

449 OS.insert(F);

450 return F;

451}

452

455 MCContext &Ctx = Asm.getContext();

459 const MCExpr *AddrDelta =

461 int64_t Result;

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

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

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

468}

469

472 size_t LocBegin;

473 size_t LocEnd;

475

476 if (LocBegin >= LocEnd)

477 return;

479 if (Locs.empty())

480 return;

481

482

483#ifndef NDEBUG

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

485 for (const MCCVLoc &Loc : Locs) {

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

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

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

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

491 }

492 }

493#endif

494

495

496

497

500 StartLoc.setFileNum(Frag.StartFileId);

501 StartLoc.setLine(Frag.StartLineNum);

502 bool HaveOpenRange = false;

503

506 LastSourceLoc.File = Frag.StartFileId;

507 LastSourceLoc.Line = Frag.StartLineNum;

508

510

512 Buffer.clear();

513 for (const MCCVLoc &Loc : Locs) {

514

515

516

517 constexpr uint32_t InlineSiteSize = 12;

518 constexpr uint32_t AnnotationSize = 8;

519 size_t MaxBufferSize = MaxRecordLength - InlineSiteSize - AnnotationSize;

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

521 break;

522

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

524 CurSourceLoc.File = Loc.getFileNum();

525 CurSourceLoc.Line = Loc.getLine();

526 } else {

527 auto I = SiteInfo->InlinedAtMap.find(Loc.getFunctionId());

529

530

531

532 CurSourceLoc = I->second;

533 } else {

534

535

536 if (HaveOpenRange) {

538 compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);

540 LastLabel = Loc.getLabel();

541 }

542 HaveOpenRange = false;

543 continue;

544 }

545 }

546

547

548

549

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

551 CurSourceLoc.Line == LastSourceLoc.Line)

552 continue;

553

554 HaveOpenRange = true;

555

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

557 unsigned FileOffset = static_cast<const MCConstantExpr *>(

558 Files[CurSourceLoc.File - 1]

559 .ChecksumTableOffset->getVariableValue())

560 ->getValue();

563 }

564

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

567 unsigned CodeDelta = computeLabelDiff(Asm, LastLabel, Loc.getLabel());

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

569

570

571

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

573 compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset,

574 Buffer);

576 } else {

577

578 if (LineDelta != 0) {

579 compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);

581 }

582 compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer);

584 }

585

586 LastLabel = Loc.getLabel();

587 LastSourceLoc = CurSourceLoc;

588 }

589

590 assert(HaveOpenRange);

591

592 unsigned EndSymLength =

594 unsigned LocAfterLength = ~0U;

596 if (!LocAfter.empty()) {

597

598 const MCCVLoc &Loc = LocAfter[0];

601 }

602

603 compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);

605}

606

609 MCContext &Ctx = Asm.getContext();

611 Contents.clear();

613 Fixups.clear();

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}

Analysis containing CSE Info

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 unsigned computeLabelDiff(const MCAssembler &Asm, const MCSymbol *Begin, const MCSymbol *End)

static uint32_t encodeSignedNumber(uint32_t Data)

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

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

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

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)

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

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

Encodes the binary annotations once we have a layout.

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

Emits a line table substream.

void emitFileChecksums(MCObjectStreamer &OS)

Emits the file checksum substream.

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.

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

MCCVFunctionInfo * getCVFunctionInfo(unsigned FuncId)

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

bool recordFunctionId(unsigned FuncId)

Records the function id of a normal function.

void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo)

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

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

void addLineEntry(const MCCVLoc &LineEntry)

Add a line entry.

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

Records the function id of an inlined call site.

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

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

void emitStringTable(MCObjectStreamer &OS)

Emits the string table substream.

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.

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

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

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

Add something to the string table.

Binary assembler expressions.

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

static 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

SmallString< 8 > & getContents()

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

void setFileNum(unsigned fileNum)

Set the FileNum of this MCCVLoc.

unsigned getFileNum() const

Get the FileNum of this MCCVLoc.

const MCSymbol * getLabel() const

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 const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Context object for machine code objects.

MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

F * allocFragment(Args &&...args)

Fragment for data and encoded instructions.

void setContents(ArrayRef< char > C)

SmallVectorImpl< MCFixup > & getFixups()

SmallVectorImpl< char > & getContents()

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

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, SMLoc Loc=SMLoc())

Streaming object file generation interface.

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

Streaming machine code generation interface.

Represent a reference to a symbol from inside an expression.

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

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 append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

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.

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.

@ FK_SecRel_2

A two-byte section relative fixup.

@ FK_SecRel_4

A four-byte section relative fixup.

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

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 ....

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)