LLVM  6.0.0svn
MCCodeView.cpp
Go to the documentation of this file.
1 //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Holds state from .cv_file and .cv_loc directives for later emission.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/MC/MCCodeView.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/BinaryFormat/COFF.h"
21 #include "llvm/MC/MCAsmLayout.h"
22 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCValue.h"
26 
27 using namespace llvm;
28 using namespace llvm::codeview;
29 
31 
33  // If someone inserted strings into the string table but never actually
34  // emitted them somewhere, clean up the fragment.
35  if (!InsertedStrTabFragment)
36  delete StrTabFragment;
37 }
38 
39 /// This is a valid number for use with .cv_loc if we've already seen a .cv_file
40 /// for it.
41 bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
42  unsigned Idx = FileNumber - 1;
43  if (Idx < Files.size())
44  return Files[Idx].Assigned;
45  return false;
46 }
47 
48 bool CodeViewContext::addFile(MCStreamer &OS, unsigned FileNumber,
49  StringRef Filename,
50  ArrayRef<uint8_t> ChecksumBytes,
51  uint8_t ChecksumKind) {
52  assert(FileNumber > 0);
53  auto FilenameOffset = addToStringTable(Filename);
54  Filename = FilenameOffset.first;
55  unsigned Idx = FileNumber - 1;
56  if (Idx >= Files.size())
57  Files.resize(Idx + 1);
58 
59  if (Filename.empty())
60  Filename = "<stdin>";
61 
62  if (Files[Idx].Assigned)
63  return false;
64 
65  FilenameOffset = addToStringTable(Filename);
66  Filename = FilenameOffset.first;
67  unsigned Offset = FilenameOffset.second;
68 
69  auto ChecksumOffsetSymbol =
70  OS.getContext().createTempSymbol("checksum_offset", false);
71  Files[Idx].StringTableOffset = Offset;
72  Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;
73  Files[Idx].Assigned = true;
74  Files[Idx].Checksum = ChecksumBytes;
75  Files[Idx].ChecksumKind = ChecksumKind;
76 
77  return true;
78 }
79 
80 bool CodeViewContext::recordFunctionId(unsigned FuncId) {
81  if (FuncId >= Functions.size())
82  Functions.resize(FuncId + 1);
83 
84  // Return false if this function info was already allocated.
85  if (!Functions[FuncId].isUnallocatedFunctionInfo())
86  return false;
87 
88  // Mark this as an allocated normal function, and leave the rest alone.
89  Functions[FuncId].ParentFuncIdPlusOne = MCCVFunctionInfo::FunctionSentinel;
90  return true;
91 }
92 
93 bool CodeViewContext::recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
94  unsigned IAFile, unsigned IALine,
95  unsigned IACol) {
96  if (FuncId >= Functions.size())
97  Functions.resize(FuncId + 1);
98 
99  // Return false if this function info was already allocated.
100  if (!Functions[FuncId].isUnallocatedFunctionInfo())
101  return false;
102 
103  MCCVFunctionInfo::LineInfo InlinedAt;
104  InlinedAt.File = IAFile;
105  InlinedAt.Line = IALine;
106  InlinedAt.Col = IACol;
107 
108  // Mark this as an inlined call site and record call site line info.
109  MCCVFunctionInfo *Info = &Functions[FuncId];
110  Info->ParentFuncIdPlusOne = IAFunc + 1;
111  Info->InlinedAt = InlinedAt;
112 
113  // Walk up the call chain adding this function id to the InlinedAtMap of all
114  // transitive callers until we hit a real function.
115  while (Info->isInlinedCallSite()) {
116  InlinedAt = Info->InlinedAt;
117  Info = getCVFunctionInfo(Info->getParentFuncId());
118  Info->InlinedAtMap[FuncId] = InlinedAt;
119  }
120 
121  return true;
122 }
123 
124 MCDataFragment *CodeViewContext::getStringTableFragment() {
125  if (!StrTabFragment) {
126  StrTabFragment = new MCDataFragment();
127  // Start a new string table out with a null byte.
128  StrTabFragment->getContents().push_back('\0');
129  }
130  return StrTabFragment;
131 }
132 
133 std::pair<StringRef, unsigned> CodeViewContext::addToStringTable(StringRef S) {
134  SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents();
135  auto Insertion =
136  StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
137  // Return the string from the table, since it is stable.
138  std::pair<StringRef, unsigned> Ret =
139  std::make_pair(Insertion.first->first(), Insertion.first->second);
140  if (Insertion.second) {
141  // The string map key is always null terminated.
142  Contents.append(Ret.first.begin(), Ret.first.end() + 1);
143  }
144  return Ret;
145 }
146 
147 unsigned CodeViewContext::getStringTableOffset(StringRef S) {
148  // A string table offset of zero is always the empty string.
149  if (S.empty())
150  return 0;
151  auto I = StringTable.find(S);
152  assert(I != StringTable.end());
153  return I->second;
154 }
155 
157  MCContext &Ctx = OS.getContext();
158  MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false),
159  *StringEnd = Ctx.createTempSymbol("strtab_end", false);
160 
162  OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4);
163  OS.EmitLabel(StringBegin);
164 
165  // Put the string table data fragment here, if we haven't already put it
166  // somewhere else. If somebody wants two string tables in their .s file, one
167  // will just be empty.
168  if (!InsertedStrTabFragment) {
169  OS.insert(getStringTableFragment());
170  InsertedStrTabFragment = true;
171  }
172 
173  OS.EmitValueToAlignment(4, 0);
174 
175  OS.EmitLabel(StringEnd);
176 }
177 
179  // Do nothing if there are no file checksums. Microsoft's linker rejects empty
180  // CodeView substreams.
181  if (Files.empty())
182  return;
183 
184  MCContext &Ctx = OS.getContext();
185  MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false),
186  *FileEnd = Ctx.createTempSymbol("filechecksums_end", false);
187 
189  OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
190  OS.EmitLabel(FileBegin);
191 
192  unsigned CurrentOffset = 0;
193 
194  // Emit an array of FileChecksum entries. We index into this table using the
195  // user-provided file number. Each entry may be a variable number of bytes
196  // determined by the checksum kind and size.
197  for (auto File : Files) {
198  OS.EmitAssignment(File.ChecksumTableOffset,
199  MCConstantExpr::create(CurrentOffset, Ctx));
200  CurrentOffset += 4; // String table offset.
201  if (!File.ChecksumKind) {
202  CurrentOffset +=
203  4; // One byte each for checksum size and kind, then align to 4 bytes.
204  } else {
205  CurrentOffset += 2; // One byte each for checksum size and kind.
206  CurrentOffset += File.Checksum.size();
207  CurrentOffset = alignTo(CurrentOffset, 4);
208  }
209 
210  OS.EmitIntValue(File.StringTableOffset, 4);
211 
212  if (!File.ChecksumKind) {
213  // There is no checksum. Therefore zero the next two fields and align
214  // back to 4 bytes.
215  OS.EmitIntValue(0, 4);
216  continue;
217  }
218  OS.EmitIntValue(static_cast<uint8_t>(File.Checksum.size()), 1);
219  OS.EmitIntValue(File.ChecksumKind, 1);
220  OS.EmitBytes(toStringRef(File.Checksum));
221  OS.EmitValueToAlignment(4);
222  }
223 
224  OS.EmitLabel(FileEnd);
225 
226  ChecksumOffsetsAssigned = true;
227 }
228 
229 // Output checksum table offset of the given file number. It is possible that
230 // not all files have been registered yet, and so the offset cannot be
231 // calculated. In this case a symbol representing the offset is emitted, and
232 // the value of this symbol will be fixed up at a later time.
234  unsigned FileNo) {
235  unsigned Idx = FileNo - 1;
236 
237  if (Idx >= Files.size())
238  Files.resize(Idx + 1);
239 
240  if (ChecksumOffsetsAssigned) {
241  OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
242  return;
243  }
244 
245  const MCSymbolRefExpr *SRE =
246  MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
247 
248  OS.EmitValueImpl(SRE, 4);
249 }
250 
252  unsigned FuncId,
253  const MCSymbol *FuncBegin,
254  const MCSymbol *FuncEnd) {
255  MCContext &Ctx = OS.getContext();
256  MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false),
257  *LineEnd = Ctx.createTempSymbol("linetable_end", false);
258 
259  OS.EmitIntValue(unsigned(DebugSubsectionKind::Lines), 4);
260  OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
261  OS.EmitLabel(LineBegin);
262  OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0);
263  OS.EmitCOFFSectionIndex(FuncBegin);
264 
265  // Actual line info.
266  std::vector<MCCVLineEntry> Locs = getFunctionLineEntries(FuncId);
267  bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) {
268  return LineEntry.getColumn() != 0;
269  });
270  OS.EmitIntValue(HaveColumns ? int(LF_HaveColumns) : 0, 2);
271  OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4);
272 
273  for (auto I = Locs.begin(), E = Locs.end(); I != E;) {
274  // Emit a file segment for the run of locations that share a file id.
275  unsigned CurFileNum = I->getFileNum();
276  auto FileSegEnd =
277  std::find_if(I, E, [CurFileNum](const MCCVLineEntry &Loc) {
278  return Loc.getFileNum() != CurFileNum;
279  });
280  unsigned EntryCount = FileSegEnd - I;
281  OS.AddComment(
282  "Segment for file '" +
283  Twine(getStringTableFragment()
284  ->getContents()[Files[CurFileNum - 1].StringTableOffset]) +
285  "' begins");
286  OS.EmitCVFileChecksumOffsetDirective(CurFileNum);
287  OS.EmitIntValue(EntryCount, 4);
288  uint32_t SegmentSize = 12;
289  SegmentSize += 8 * EntryCount;
290  if (HaveColumns)
291  SegmentSize += 4 * EntryCount;
292  OS.EmitIntValue(SegmentSize, 4);
293 
294  for (auto J = I; J != FileSegEnd; ++J) {
295  OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4);
296  unsigned LineData = J->getLine();
297  if (J->isStmt())
298  LineData |= LineInfo::StatementFlag;
299  OS.EmitIntValue(LineData, 4);
300  }
301  if (HaveColumns) {
302  for (auto J = I; J != FileSegEnd; ++J) {
303  OS.EmitIntValue(J->getColumn(), 2);
304  OS.EmitIntValue(0, 2);
305  }
306  }
307  I = FileSegEnd;
308  }
309  OS.EmitLabel(LineEnd);
310 }
311 
313  if (isUInt<7>(Data)) {
314  Buffer.push_back(Data);
315  return true;
316  }
317 
318  if (isUInt<14>(Data)) {
319  Buffer.push_back((Data >> 8) | 0x80);
320  Buffer.push_back(Data & 0xff);
321  return true;
322  }
323 
324  if (isUInt<29>(Data)) {
325  Buffer.push_back((Data >> 24) | 0xC0);
326  Buffer.push_back((Data >> 16) & 0xff);
327  Buffer.push_back((Data >> 8) & 0xff);
328  Buffer.push_back(Data & 0xff);
329  return true;
330  }
331 
332  return false;
333 }
334 
336  SmallVectorImpl<char> &Buffer) {
337  return compressAnnotation(static_cast<uint32_t>(Annotation), Buffer);
338 }
339 
341  if (Data >> 31)
342  return ((-Data) << 1) | 1;
343  return Data << 1;
344 }
345 
347  unsigned PrimaryFunctionId,
348  unsigned SourceFileId,
349  unsigned SourceLineNum,
350  const MCSymbol *FnStartSym,
351  const MCSymbol *FnEndSym) {
352  // Create and insert a fragment into the current section that will be encoded
353  // later.
354  new MCCVInlineLineTableFragment(PrimaryFunctionId, SourceFileId,
355  SourceLineNum, FnStartSym, FnEndSym,
356  OS.getCurrentSectionOnly());
357 }
358 
360  MCObjectStreamer &OS,
361  ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
362  StringRef FixedSizePortion) {
363  // Create and insert a fragment into the current section that will be encoded
364  // later.
365  new MCCVDefRangeFragment(Ranges, FixedSizePortion,
366  OS.getCurrentSectionOnly());
367 }
368 
369 static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin,
370  const MCSymbol *End) {
371  MCContext &Ctx = Layout.getAssembler().getContext();
373  const MCExpr *BeginRef = MCSymbolRefExpr::create(Begin, Variant, Ctx),
374  *EndRef = MCSymbolRefExpr::create(End, Variant, Ctx);
375  const MCExpr *AddrDelta =
376  MCBinaryExpr::create(MCBinaryExpr::Sub, EndRef, BeginRef, Ctx);
377  int64_t Result;
378  bool Success = AddrDelta->evaluateKnownAbsolute(Result, Layout);
379  assert(Success && "failed to evaluate label difference as absolute");
380  (void)Success;
381  assert(Result >= 0 && "negative label difference requested");
382  assert(Result < UINT_MAX && "label difference greater than 2GB");
383  return unsigned(Result);
384 }
385 
388  size_t LocBegin;
389  size_t LocEnd;
390  std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId);
391 
392  // Include all child inline call sites in our .cv_loc extent.
393  MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId);
394  for (auto &KV : SiteInfo->InlinedAtMap) {
395  unsigned ChildId = KV.first;
396  auto Extent = getLineExtent(ChildId);
397  LocBegin = std::min(LocBegin, Extent.first);
398  LocEnd = std::max(LocEnd, Extent.second);
399  }
400 
401  if (LocBegin >= LocEnd)
402  return;
403  ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
404  if (Locs.empty())
405  return;
406 
407  // Make an artificial start location using the function start and the inlinee
408  // lines start location information. All deltas start relative to this
409  // location.
410  MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front()));
411  StartLoc.setFileNum(Frag.StartFileId);
412  StartLoc.setLine(Frag.StartLineNum);
413  bool HaveOpenRange = false;
414 
415  const MCSymbol *LastLabel = Frag.getFnStartSym();
416  MCCVFunctionInfo::LineInfo LastSourceLoc, CurSourceLoc;
417  LastSourceLoc.File = Frag.StartFileId;
418  LastSourceLoc.Line = Frag.StartLineNum;
419 
420  SmallVectorImpl<char> &Buffer = Frag.getContents();
421  Buffer.clear(); // Clear old contents if we went through relaxation.
422  for (const MCCVLineEntry &Loc : Locs) {
423  // Exit early if our line table would produce an oversized InlineSiteSym
424  // record. Account for the ChangeCodeLength annotation emitted after the
425  // loop ends.
426  constexpr uint32_t InlineSiteSize = 12;
427  constexpr uint32_t AnnotationSize = 8;
428  size_t MaxBufferSize = MaxRecordLength - InlineSiteSize - AnnotationSize;
429  if (Buffer.size() >= MaxBufferSize)
430  break;
431 
432  if (Loc.getFunctionId() == Frag.SiteFuncId) {
433  CurSourceLoc.File = Loc.getFileNum();
434  CurSourceLoc.Line = Loc.getLine();
435  } else {
436  auto I = SiteInfo->InlinedAtMap.find(Loc.getFunctionId());
437  if (I != SiteInfo->InlinedAtMap.end()) {
438  // This .cv_loc is from a child inline call site. Use the source
439  // location of the inlined call site instead of the .cv_loc directive
440  // source location.
441  CurSourceLoc = I->second;
442  } else {
443  // We've hit a cv_loc not attributed to this inline call site. Use this
444  // label to end the PC range.
445  if (HaveOpenRange) {
446  unsigned Length = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
448  compressAnnotation(Length, Buffer);
449  LastLabel = Loc.getLabel();
450  }
451  HaveOpenRange = false;
452  continue;
453  }
454  }
455 
456  // Skip this .cv_loc if we have an open range and this isn't a meaningful
457  // source location update. The current table format does not support column
458  // info, so we can skip updates for those.
459  if (HaveOpenRange && CurSourceLoc.File == LastSourceLoc.File &&
460  CurSourceLoc.Line == LastSourceLoc.Line)
461  continue;
462 
463  HaveOpenRange = true;
464 
465  if (CurSourceLoc.File != LastSourceLoc.File) {
466  unsigned FileOffset = static_cast<const MCConstantExpr *>(
467  Files[CurSourceLoc.File - 1]
468  .ChecksumTableOffset->getVariableValue())
469  ->getValue();
471  compressAnnotation(FileOffset, Buffer);
472  }
473 
474  int LineDelta = CurSourceLoc.Line - LastSourceLoc.Line;
475  unsigned EncodedLineDelta = encodeSignedNumber(LineDelta);
476  unsigned CodeDelta = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
477  if (CodeDelta == 0 && LineDelta != 0) {
479  compressAnnotation(EncodedLineDelta, Buffer);
480  } else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) {
481  // The ChangeCodeOffsetAndLineOffset combination opcode is used when the
482  // encoded line delta uses 3 or fewer set bits and the code offset fits
483  // in one nibble.
484  unsigned Operand = (EncodedLineDelta << 4) | CodeDelta;
486  Buffer);
487  compressAnnotation(Operand, Buffer);
488  } else {
489  // Otherwise use the separate line and code deltas.
490  if (LineDelta != 0) {
492  compressAnnotation(EncodedLineDelta, Buffer);
493  }
495  compressAnnotation(CodeDelta, Buffer);
496  }
497 
498  LastLabel = Loc.getLabel();
499  LastSourceLoc = CurSourceLoc;
500  }
501 
502  assert(HaveOpenRange);
503 
504  unsigned EndSymLength =
505  computeLabelDiff(Layout, LastLabel, Frag.getFnEndSym());
506  unsigned LocAfterLength = ~0U;
507  ArrayRef<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
508  if (!LocAfter.empty()) {
509  // Only try to compute this difference if we're in the same section.
510  const MCCVLineEntry &Loc = LocAfter[0];
511  if (&Loc.getLabel()->getSection(false) == &LastLabel->getSection(false))
512  LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
513  }
514 
516  compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer);
517 }
518 
520  MCCVDefRangeFragment &Frag) {
521  MCContext &Ctx = Layout.getAssembler().getContext();
522  SmallVectorImpl<char> &Contents = Frag.getContents();
523  Contents.clear();
525  Fixups.clear();
526  raw_svector_ostream OS(Contents);
527 
528  // Compute all the sizes up front.
529  SmallVector<std::pair<unsigned, unsigned>, 4> GapAndRangeSizes;
530  const MCSymbol *LastLabel = nullptr;
531  for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) {
532  unsigned GapSize =
533  LastLabel ? computeLabelDiff(Layout, LastLabel, Range.first) : 0;
534  unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second);
535  GapAndRangeSizes.push_back({GapSize, RangeSize});
536  LastLabel = Range.second;
537  }
538 
539  // Write down each range where the variable is defined.
540  for (size_t I = 0, E = Frag.getRanges().size(); I != E;) {
541  // If the range size of multiple consecutive ranges is under the max,
542  // combine the ranges and emit some gaps.
543  const MCSymbol *RangeBegin = Frag.getRanges()[I].first;
544  unsigned RangeSize = GapAndRangeSizes[I].second;
545  size_t J = I + 1;
546  for (; J != E; ++J) {
547  unsigned GapAndRangeSize = GapAndRangeSizes[J].first + GapAndRangeSizes[J].second;
548  if (RangeSize + GapAndRangeSize > MaxDefRange)
549  break;
550  RangeSize += GapAndRangeSize;
551  }
552  unsigned NumGaps = J - I - 1;
553 
555 
556  unsigned Bias = 0;
557  // We must split the range into chunks of MaxDefRange, this is a fundamental
558  // limitation of the file format.
559  do {
560  uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize);
561 
562  const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(RangeBegin, Ctx);
563  const MCBinaryExpr *BE =
564  MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx);
565  MCValue Res;
566  BE->evaluateAsRelocatable(Res, &Layout, /*Fixup=*/nullptr);
567 
568  // Each record begins with a 2-byte number indicating how large the record
569  // is.
570  StringRef FixedSizePortion = Frag.getFixedSizePortion();
571  // Our record is a fixed sized prefix and a LocalVariableAddrRange that we
572  // are artificially constructing.
573  size_t RecordSize = FixedSizePortion.size() +
574  sizeof(LocalVariableAddrRange) + 4 * NumGaps;
575  // Write out the record size.
576  LEWriter.write<uint16_t>(RecordSize);
577  // Write out the fixed size prefix.
578  OS << FixedSizePortion;
579  // Make space for a fixup that will eventually have a section relative
580  // relocation pointing at the offset where the variable becomes live.
581  Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_4));
582  LEWriter.write<uint32_t>(0); // Fixup for code start.
583  // Make space for a fixup that will record the section index for the code.
584  Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2));
585  LEWriter.write<uint16_t>(0); // Fixup for section index.
586  // Write down the range's extent.
587  LEWriter.write<uint16_t>(Chunk);
588 
589  // Move on to the next range.
590  Bias += Chunk;
591  RangeSize -= Chunk;
592  } while (RangeSize > 0);
593 
594  // Emit the gaps afterwards.
595  assert((NumGaps == 0 || Bias <= MaxDefRange) &&
596  "large ranges should not have gaps");
597  unsigned GapStartOffset = GapAndRangeSizes[I].second;
598  for (++I; I != J; ++I) {
599  unsigned GapSize, RangeSize;
600  assert(I < GapAndRangeSizes.size());
601  std::tie(GapSize, RangeSize) = GapAndRangeSizes[I];
602  LEWriter.write<uint16_t>(GapStartOffset);
603  LEWriter.write<uint16_t>(GapSize);
604  GapStartOffset += GapSize + RangeSize;
605  }
606  }
607 }
608 
609 //
610 // This is called when an instruction is assembled into the specified section
611 // and if there is information from the last .cv_loc directive that has yet to have
612 // a line entry made for it is made.
613 //
615  CodeViewContext &CVC = MCOS->getContext().getCVContext();
616  if (!CVC.getCVLocSeen())
617  return;
618 
619  // Create a symbol at in the current section for use in the line entry.
620  MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
621  // Set the value of the symbol to use for the MCCVLineEntry.
622  MCOS->EmitLabel(LineSym);
623 
624  // Get the current .loc info saved in the context.
625  const MCCVLoc &CVLoc = CVC.getCurrentCVLoc();
626 
627  // Create a (local) line entry with the symbol and the current .loc info.
628  MCCVLineEntry LineEntry(LineSym, CVLoc);
629 
630  // clear CVLocSeen saying the current .loc info is now used.
631  CVC.clearCVLocSeen();
632 
633  // Add the line entry to this section's entries.
634  CVC.addLineEntry(LineEntry);
635 }
const T & front() const
front - Get the first element.
Definition: ArrayRef.h:152
void push_back(const T &Elt)
Definition: SmallVector.h:212
void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F)
Definition: MCCodeView.cpp:519
void EmitBytes(StringRef Data) override
Emit the bytes in Data into the output.
Instances of this class represent the information from a .cv_loc directive.
Definition: MCCodeView.h:32
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId, const MCSymbol *FuncBegin, const MCSymbol *FuncEnd)
Emits a line table substream.
Definition: MCCodeView.cpp:251
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:305
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
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.
Definition: MCStreamer.cpp:127
This represents an "assembler immediate".
Definition: MCValue.h:40
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
MCSection & getSection(bool SetUsed=true) const
Get the section associated with a defined, non-absolute symbol.
Definition: MCSymbol.h:268
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:136
SmallString< 8 > & getContents()
Definition: MCFragment.h:616
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
std::pair< StringRef, unsigned > addToStringTable(StringRef S)
Add something to the string table.
Definition: MCCodeView.cpp:133
static void Make(MCObjectStreamer *MCOS)
Definition: MCCodeView.cpp:614
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:489
void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override
This implements the CodeView &#39;.cv_filechecksumoffset&#39; assembler directive.
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:677
StringRef getFixedSizePortion() const
Definition: MCFragment.h:649
DenseMap< unsigned, LineInfo > InlinedAtMap
Map from inlined call site id to the inlined at location to use for that call site.
Definition: MCCodeView.h:138
bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename, ArrayRef< uint8_t > ChecksumBytes, uint8_t ChecksumKind)
Definition: MCCodeView.cpp:48
static bool compressAnnotation(uint32_t Data, SmallVectorImpl< char > &Buffer)
Definition: MCCodeView.cpp:312
void emitInlineLineTableForFunction(MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)
Definition: MCCodeView.cpp:346
MCContext & getContext() const
Definition: MCAssembler.h:259
MCContext & getContext() const
Definition: MCStreamer.h:234
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:29
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:165
static uint32_t encodeSignedNumber(uint32_t Data)
Definition: MCCodeView.cpp:340
A four-byte section relative fixup.
Definition: MCFixup.h:42
Context object for machine code objects.
Definition: MCContext.h:59
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
Definition: MCStreamer.h:282
void emitDefRange(MCObjectStreamer &OS, ArrayRef< std::pair< const MCSymbol *, const MCSymbol *>> Ranges, StringRef FixedSizePortion)
Definition: MCCodeView.cpp:359
A two-byte section relative fixup.
Definition: MCFixup.h:41
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:594
Streaming object file generation interface.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
bool isInlinedCallSite() const
Returns true if this represents an inlined call site, meaning ParentFuncIdPlusOne is neither zero nor...
Definition: MCCodeView.h:146
unsigned getParentFuncId() const
Definition: MCCodeView.h:151
MCAssembler & getAssembler() const
Get the assembler object this is a layout for.
Definition: MCAsmLayout.h:51
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:443
SmallVectorImpl< char > & getContents()
Definition: MCFragment.h:183
virtual void EmitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers...
Definition: MCStreamer.cpp:88
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:148
const MCCVLoc & getCurrentCVLoc()
Definition: MCCodeView.h:205
void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) override
Emit the absolute difference between two symbols if possible.
void encodeInlineLineTable(MCAsmLayout &Layout, MCCVInlineLineTableFragment &F)
Encodes the binary annotations once we have a layout.
Definition: MCCodeView.cpp:386
Streaming machine code generation interface.
Definition: MCStreamer.h:169
bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const
Definition: MCExpr.cpp:431
MCSymbol * createTempSymbol(bool CanBeUnnamed=true)
Create and return a new assembler temporary symbol with a unique but unspecified name.
Definition: MCContext.cpp:215
void EmitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
void write(ArrayRef< value_type > Vals)
Definition: EndianStream.h:30
void insert(MCFragment *F)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
SmallVectorImpl< MCFixup > & getFixups()
Definition: MCFragment.h:208
bool any_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:820
static const unsigned End
void setFileNum(unsigned fileNum)
Set the FileNum of this MCCVLoc.
Definition: MCCodeView.h:68
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:841
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
Definition: StringExtras.h:43
Binary assembler expressions.
Definition: MCExpr.h:399
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:82
Fragment representing the .cv_def_range directive.
Definition: MCFragment.h:627
void setLine(unsigned line)
Set the Line of this MCCVLoc.
Definition: MCCodeView.h:71
void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0) override
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void addLineEntry(const MCCVLineEntry &LineEntry)
Add a line entry.
Definition: MCCodeView.h:210
static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin, const MCSymbol *End)
Definition: MCCodeView.cpp:369
unsigned ParentFuncIdPlusOne
If this represents an inlined call site, then ParentFuncIdPlusOne will be the parent function id plus...
Definition: MCCodeView.h:118
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:864
unsigned getFileNum() const
Get the FileNum of this MCCVLoc.
Definition: MCCodeView.h:54
const MCSymbol * getFnEndSym() const
Definition: MCFragment.h:614
MCSection * getCurrentSectionOnly() const
Definition: MCStreamer.h:316
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:398
Fragment representing the binary annotations produced by the .cv_inline_linetable directive...
Definition: MCFragment.h:589
const MCSymbol * getFnStartSym() const
Definition: MCFragment.h:613
#define Success
bool recordFunctionId(unsigned FuncId)
Records the function id of a normal function.
Definition: MCCodeView.cpp:80
static void addToStringTable(raw_ostream &Out, StringRef ArcName, const NewArchiveMember &M, bool Thin)
bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol)
Records the function id of an inlined call site.
Definition: MCCodeView.cpp:93
void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override
Emit an assignment of Value to Symbol.
#define I(x, y, z)
Definition: MD5.cpp:58
bool isValidFileNumber(unsigned FileNumber) const
This is a valid number for use with .cv_loc if we&#39;ve already seen a .cv_file for it.
Definition: MCCodeView.cpp:41
void emitStringTable(MCObjectStreamer &OS)
Emits the string table substream.
Definition: MCCodeView.cpp:156
void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo)
Emits the offset into the checksum table of the given file number.
Definition: MCCodeView.cpp:233
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.
Instances of this class represent the line information for the CodeView line table entries...
Definition: MCCodeView.h:88
CodeViewContext & getCVContext()
Definition: MCContext.cpp:560
Fragment for data and encoded instructions.
Definition: MCFragment.h:226
virtual void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)
Emits a COFF section relative relocation.
Definition: MCStreamer.cpp:788
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCSymbol * getLabel() const
Definition: MCCodeView.h:100
ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > getRanges() const
Definition: MCFragment.h:645
unsigned getColumn() const
Get the Column of this MCCVLoc.
Definition: MCCodeView.h:60
Subtraction.
Definition: MCExpr.h:423
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Information describing a function or inlined call site introduced by .cv_func_id or ...
Definition: MCCodeView.h:112
void emitFileChecksums(MCObjectStreamer &OS)
Emits the file checksum substream.
Definition: MCCodeView.cpp:178
virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol)
Emits a COFF section index.
Definition: MCStreamer.cpp:785
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:159
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:144
Holds state from .cv_file and .cv_loc directives for later emission.
Definition: MCCodeView.h:158