xref: /aosp_15_r20/external/llvm/lib/MC/MCCodeView.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Holds state from .cv_file and .cv_loc directives for later emission.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCCodeView.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmLayout.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/CodeView.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/Line.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectStreamer.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/COFF.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h"
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker using namespace llvm;
27*9880d681SAndroid Build Coastguard Worker using namespace llvm::codeview;
28*9880d681SAndroid Build Coastguard Worker 
CodeViewContext()29*9880d681SAndroid Build Coastguard Worker CodeViewContext::CodeViewContext() {}
30*9880d681SAndroid Build Coastguard Worker 
~CodeViewContext()31*9880d681SAndroid Build Coastguard Worker CodeViewContext::~CodeViewContext() {
32*9880d681SAndroid Build Coastguard Worker   // If someone inserted strings into the string table but never actually
33*9880d681SAndroid Build Coastguard Worker   // emitted them somewhere, clean up the fragment.
34*9880d681SAndroid Build Coastguard Worker   if (!InsertedStrTabFragment)
35*9880d681SAndroid Build Coastguard Worker     delete StrTabFragment;
36*9880d681SAndroid Build Coastguard Worker }
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker /// This is a valid number for use with .cv_loc if we've already seen a .cv_file
39*9880d681SAndroid Build Coastguard Worker /// for it.
isValidFileNumber(unsigned FileNumber) const40*9880d681SAndroid Build Coastguard Worker bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
41*9880d681SAndroid Build Coastguard Worker   unsigned Idx = FileNumber - 1;
42*9880d681SAndroid Build Coastguard Worker   if (Idx < Filenames.size())
43*9880d681SAndroid Build Coastguard Worker     return !Filenames[Idx].empty();
44*9880d681SAndroid Build Coastguard Worker   return false;
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker 
addFile(unsigned FileNumber,StringRef Filename)47*9880d681SAndroid Build Coastguard Worker bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
48*9880d681SAndroid Build Coastguard Worker   assert(FileNumber > 0);
49*9880d681SAndroid Build Coastguard Worker   Filename = addToStringTable(Filename);
50*9880d681SAndroid Build Coastguard Worker   unsigned Idx = FileNumber - 1;
51*9880d681SAndroid Build Coastguard Worker   if (Idx >= Filenames.size())
52*9880d681SAndroid Build Coastguard Worker     Filenames.resize(Idx + 1);
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker   if (Filename.empty())
55*9880d681SAndroid Build Coastguard Worker     Filename = "<stdin>";
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker   if (!Filenames[Idx].empty())
58*9880d681SAndroid Build Coastguard Worker     return false;
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker   // FIXME: We should store the string table offset of the filename, rather than
61*9880d681SAndroid Build Coastguard Worker   // the filename itself for efficiency.
62*9880d681SAndroid Build Coastguard Worker   Filename = addToStringTable(Filename);
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker   Filenames[Idx] = Filename;
65*9880d681SAndroid Build Coastguard Worker   return true;
66*9880d681SAndroid Build Coastguard Worker }
67*9880d681SAndroid Build Coastguard Worker 
getStringTableFragment()68*9880d681SAndroid Build Coastguard Worker MCDataFragment *CodeViewContext::getStringTableFragment() {
69*9880d681SAndroid Build Coastguard Worker   if (!StrTabFragment) {
70*9880d681SAndroid Build Coastguard Worker     StrTabFragment = new MCDataFragment();
71*9880d681SAndroid Build Coastguard Worker     // Start a new string table out with a null byte.
72*9880d681SAndroid Build Coastguard Worker     StrTabFragment->getContents().push_back('\0');
73*9880d681SAndroid Build Coastguard Worker   }
74*9880d681SAndroid Build Coastguard Worker   return StrTabFragment;
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker 
addToStringTable(StringRef S)77*9880d681SAndroid Build Coastguard Worker StringRef CodeViewContext::addToStringTable(StringRef S) {
78*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents();
79*9880d681SAndroid Build Coastguard Worker   auto Insertion =
80*9880d681SAndroid Build Coastguard Worker       StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
81*9880d681SAndroid Build Coastguard Worker   // Return the string from the table, since it is stable.
82*9880d681SAndroid Build Coastguard Worker   S = Insertion.first->first();
83*9880d681SAndroid Build Coastguard Worker   if (Insertion.second) {
84*9880d681SAndroid Build Coastguard Worker     // The string map key is always null terminated.
85*9880d681SAndroid Build Coastguard Worker     Contents.append(S.begin(), S.end() + 1);
86*9880d681SAndroid Build Coastguard Worker   }
87*9880d681SAndroid Build Coastguard Worker   return S;
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker 
getStringTableOffset(StringRef S)90*9880d681SAndroid Build Coastguard Worker unsigned CodeViewContext::getStringTableOffset(StringRef S) {
91*9880d681SAndroid Build Coastguard Worker   // A string table offset of zero is always the empty string.
92*9880d681SAndroid Build Coastguard Worker   if (S.empty())
93*9880d681SAndroid Build Coastguard Worker     return 0;
94*9880d681SAndroid Build Coastguard Worker   auto I = StringTable.find(S);
95*9880d681SAndroid Build Coastguard Worker   assert(I != StringTable.end());
96*9880d681SAndroid Build Coastguard Worker   return I->second;
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker 
emitStringTable(MCObjectStreamer & OS)99*9880d681SAndroid Build Coastguard Worker void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
100*9880d681SAndroid Build Coastguard Worker   MCContext &Ctx = OS.getContext();
101*9880d681SAndroid Build Coastguard Worker   MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false),
102*9880d681SAndroid Build Coastguard Worker            *StringEnd = Ctx.createTempSymbol("strtab_end", false);
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(unsigned(ModuleSubstreamKind::StringTable), 4);
105*9880d681SAndroid Build Coastguard Worker   OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4);
106*9880d681SAndroid Build Coastguard Worker   OS.EmitLabel(StringBegin);
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker   // Put the string table data fragment here, if we haven't already put it
109*9880d681SAndroid Build Coastguard Worker   // somewhere else. If somebody wants two string tables in their .s file, one
110*9880d681SAndroid Build Coastguard Worker   // will just be empty.
111*9880d681SAndroid Build Coastguard Worker   if (!InsertedStrTabFragment) {
112*9880d681SAndroid Build Coastguard Worker     OS.insert(getStringTableFragment());
113*9880d681SAndroid Build Coastguard Worker     InsertedStrTabFragment = true;
114*9880d681SAndroid Build Coastguard Worker   }
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker   OS.EmitValueToAlignment(4, 0);
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker   OS.EmitLabel(StringEnd);
119*9880d681SAndroid Build Coastguard Worker }
120*9880d681SAndroid Build Coastguard Worker 
emitFileChecksums(MCObjectStreamer & OS)121*9880d681SAndroid Build Coastguard Worker void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
122*9880d681SAndroid Build Coastguard Worker   // Do nothing if there are no file checksums. Microsoft's linker rejects empty
123*9880d681SAndroid Build Coastguard Worker   // CodeView substreams.
124*9880d681SAndroid Build Coastguard Worker   if (Filenames.empty())
125*9880d681SAndroid Build Coastguard Worker     return;
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker   MCContext &Ctx = OS.getContext();
128*9880d681SAndroid Build Coastguard Worker   MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false),
129*9880d681SAndroid Build Coastguard Worker            *FileEnd = Ctx.createTempSymbol("filechecksums_end", false);
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(unsigned(ModuleSubstreamKind::FileChecksums), 4);
132*9880d681SAndroid Build Coastguard Worker   OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
133*9880d681SAndroid Build Coastguard Worker   OS.EmitLabel(FileBegin);
134*9880d681SAndroid Build Coastguard Worker 
135*9880d681SAndroid Build Coastguard Worker   // Emit an array of FileChecksum entries. We index into this table using the
136*9880d681SAndroid Build Coastguard Worker   // user-provided file number. Each entry is currently 8 bytes, as we don't
137*9880d681SAndroid Build Coastguard Worker   // emit checksums.
138*9880d681SAndroid Build Coastguard Worker   for (StringRef Filename : Filenames) {
139*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(getStringTableOffset(Filename), 4);
140*9880d681SAndroid Build Coastguard Worker     // Zero the next two fields and align back to 4 bytes. This indicates that
141*9880d681SAndroid Build Coastguard Worker     // no checksum is present.
142*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(0, 4);
143*9880d681SAndroid Build Coastguard Worker   }
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   OS.EmitLabel(FileEnd);
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker 
emitLineTableForFunction(MCObjectStreamer & OS,unsigned FuncId,const MCSymbol * FuncBegin,const MCSymbol * FuncEnd)148*9880d681SAndroid Build Coastguard Worker void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
149*9880d681SAndroid Build Coastguard Worker                                                unsigned FuncId,
150*9880d681SAndroid Build Coastguard Worker                                                const MCSymbol *FuncBegin,
151*9880d681SAndroid Build Coastguard Worker                                                const MCSymbol *FuncEnd) {
152*9880d681SAndroid Build Coastguard Worker   MCContext &Ctx = OS.getContext();
153*9880d681SAndroid Build Coastguard Worker   MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false),
154*9880d681SAndroid Build Coastguard Worker            *LineEnd = Ctx.createTempSymbol("linetable_end", false);
155*9880d681SAndroid Build Coastguard Worker 
156*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4);
157*9880d681SAndroid Build Coastguard Worker   OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
158*9880d681SAndroid Build Coastguard Worker   OS.EmitLabel(LineBegin);
159*9880d681SAndroid Build Coastguard Worker   OS.EmitCOFFSecRel32(FuncBegin);
160*9880d681SAndroid Build Coastguard Worker   OS.EmitCOFFSectionIndex(FuncBegin);
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker   // Actual line info.
163*9880d681SAndroid Build Coastguard Worker   std::vector<MCCVLineEntry> Locs = getFunctionLineEntries(FuncId);
164*9880d681SAndroid Build Coastguard Worker   bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) {
165*9880d681SAndroid Build Coastguard Worker     return LineEntry.getColumn() != 0;
166*9880d681SAndroid Build Coastguard Worker   });
167*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(HaveColumns ? int(LineFlags::HaveColumns) : 0, 2);
168*9880d681SAndroid Build Coastguard Worker   OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4);
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker   for (auto I = Locs.begin(), E = Locs.end(); I != E;) {
171*9880d681SAndroid Build Coastguard Worker     // Emit a file segment for the run of locations that share a file id.
172*9880d681SAndroid Build Coastguard Worker     unsigned CurFileNum = I->getFileNum();
173*9880d681SAndroid Build Coastguard Worker     auto FileSegEnd =
174*9880d681SAndroid Build Coastguard Worker         std::find_if(I, E, [CurFileNum](const MCCVLineEntry &Loc) {
175*9880d681SAndroid Build Coastguard Worker           return Loc.getFileNum() != CurFileNum;
176*9880d681SAndroid Build Coastguard Worker         });
177*9880d681SAndroid Build Coastguard Worker     unsigned EntryCount = FileSegEnd - I;
178*9880d681SAndroid Build Coastguard Worker     OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +
179*9880d681SAndroid Build Coastguard Worker                   "' begins");
180*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(8 * (CurFileNum - 1), 4);
181*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(EntryCount, 4);
182*9880d681SAndroid Build Coastguard Worker     uint32_t SegmentSize = 12;
183*9880d681SAndroid Build Coastguard Worker     SegmentSize += 8 * EntryCount;
184*9880d681SAndroid Build Coastguard Worker     if (HaveColumns)
185*9880d681SAndroid Build Coastguard Worker       SegmentSize += 4 * EntryCount;
186*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(SegmentSize, 4);
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker     for (auto J = I; J != FileSegEnd; ++J) {
189*9880d681SAndroid Build Coastguard Worker       OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4);
190*9880d681SAndroid Build Coastguard Worker       unsigned LineData = J->getLine();
191*9880d681SAndroid Build Coastguard Worker       if (J->isStmt())
192*9880d681SAndroid Build Coastguard Worker         LineData |= LineInfo::StatementFlag;
193*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(LineData, 4);
194*9880d681SAndroid Build Coastguard Worker     }
195*9880d681SAndroid Build Coastguard Worker     if (HaveColumns) {
196*9880d681SAndroid Build Coastguard Worker       for (auto J = I; J != FileSegEnd; ++J) {
197*9880d681SAndroid Build Coastguard Worker         OS.EmitIntValue(J->getColumn(), 2);
198*9880d681SAndroid Build Coastguard Worker         OS.EmitIntValue(0, 2);
199*9880d681SAndroid Build Coastguard Worker       }
200*9880d681SAndroid Build Coastguard Worker     }
201*9880d681SAndroid Build Coastguard Worker     I = FileSegEnd;
202*9880d681SAndroid Build Coastguard Worker   }
203*9880d681SAndroid Build Coastguard Worker   OS.EmitLabel(LineEnd);
204*9880d681SAndroid Build Coastguard Worker }
205*9880d681SAndroid Build Coastguard Worker 
compressAnnotation(uint32_t Data,SmallVectorImpl<char> & Buffer)206*9880d681SAndroid Build Coastguard Worker static bool compressAnnotation(uint32_t Data, SmallVectorImpl<char> &Buffer) {
207*9880d681SAndroid Build Coastguard Worker   if (isUInt<7>(Data)) {
208*9880d681SAndroid Build Coastguard Worker     Buffer.push_back(Data);
209*9880d681SAndroid Build Coastguard Worker     return true;
210*9880d681SAndroid Build Coastguard Worker   }
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker   if (isUInt<14>(Data)) {
213*9880d681SAndroid Build Coastguard Worker     Buffer.push_back((Data >> 8) | 0x80);
214*9880d681SAndroid Build Coastguard Worker     Buffer.push_back(Data & 0xff);
215*9880d681SAndroid Build Coastguard Worker     return true;
216*9880d681SAndroid Build Coastguard Worker   }
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker   if (isUInt<29>(Data)) {
219*9880d681SAndroid Build Coastguard Worker     Buffer.push_back((Data >> 24) | 0xC0);
220*9880d681SAndroid Build Coastguard Worker     Buffer.push_back((Data >> 16) & 0xff);
221*9880d681SAndroid Build Coastguard Worker     Buffer.push_back((Data >> 8) & 0xff);
222*9880d681SAndroid Build Coastguard Worker     Buffer.push_back(Data & 0xff);
223*9880d681SAndroid Build Coastguard Worker     return true;
224*9880d681SAndroid Build Coastguard Worker   }
225*9880d681SAndroid Build Coastguard Worker 
226*9880d681SAndroid Build Coastguard Worker   return false;
227*9880d681SAndroid Build Coastguard Worker }
228*9880d681SAndroid Build Coastguard Worker 
compressAnnotation(BinaryAnnotationsOpCode Annotation,SmallVectorImpl<char> & Buffer)229*9880d681SAndroid Build Coastguard Worker static bool compressAnnotation(BinaryAnnotationsOpCode Annotation,
230*9880d681SAndroid Build Coastguard Worker                                SmallVectorImpl<char> &Buffer) {
231*9880d681SAndroid Build Coastguard Worker   return compressAnnotation(static_cast<uint32_t>(Annotation), Buffer);
232*9880d681SAndroid Build Coastguard Worker }
233*9880d681SAndroid Build Coastguard Worker 
encodeSignedNumber(uint32_t Data)234*9880d681SAndroid Build Coastguard Worker static uint32_t encodeSignedNumber(uint32_t Data) {
235*9880d681SAndroid Build Coastguard Worker   if (Data >> 31)
236*9880d681SAndroid Build Coastguard Worker     return ((-Data) << 1) | 1;
237*9880d681SAndroid Build Coastguard Worker   return Data << 1;
238*9880d681SAndroid Build Coastguard Worker }
239*9880d681SAndroid Build Coastguard Worker 
emitInlineLineTableForFunction(MCObjectStreamer & OS,unsigned PrimaryFunctionId,unsigned SourceFileId,unsigned SourceLineNum,const MCSymbol * FnStartSym,const MCSymbol * FnEndSym,ArrayRef<unsigned> SecondaryFunctionIds)240*9880d681SAndroid Build Coastguard Worker void CodeViewContext::emitInlineLineTableForFunction(
241*9880d681SAndroid Build Coastguard Worker     MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
242*9880d681SAndroid Build Coastguard Worker     unsigned SourceLineNum, const MCSymbol *FnStartSym,
243*9880d681SAndroid Build Coastguard Worker     const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds) {
244*9880d681SAndroid Build Coastguard Worker   // Create and insert a fragment into the current section that will be encoded
245*9880d681SAndroid Build Coastguard Worker   // later.
246*9880d681SAndroid Build Coastguard Worker   new MCCVInlineLineTableFragment(
247*9880d681SAndroid Build Coastguard Worker       PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
248*9880d681SAndroid Build Coastguard Worker       SecondaryFunctionIds, OS.getCurrentSectionOnly());
249*9880d681SAndroid Build Coastguard Worker }
250*9880d681SAndroid Build Coastguard Worker 
emitDefRange(MCObjectStreamer & OS,ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,StringRef FixedSizePortion)251*9880d681SAndroid Build Coastguard Worker void CodeViewContext::emitDefRange(
252*9880d681SAndroid Build Coastguard Worker     MCObjectStreamer &OS,
253*9880d681SAndroid Build Coastguard Worker     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
254*9880d681SAndroid Build Coastguard Worker     StringRef FixedSizePortion) {
255*9880d681SAndroid Build Coastguard Worker   // Create and insert a fragment into the current section that will be encoded
256*9880d681SAndroid Build Coastguard Worker   // later.
257*9880d681SAndroid Build Coastguard Worker   new MCCVDefRangeFragment(Ranges, FixedSizePortion,
258*9880d681SAndroid Build Coastguard Worker                            OS.getCurrentSectionOnly());
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker 
computeLabelDiff(MCAsmLayout & Layout,const MCSymbol * Begin,const MCSymbol * End)261*9880d681SAndroid Build Coastguard Worker static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin,
262*9880d681SAndroid Build Coastguard Worker                                  const MCSymbol *End) {
263*9880d681SAndroid Build Coastguard Worker   MCContext &Ctx = Layout.getAssembler().getContext();
264*9880d681SAndroid Build Coastguard Worker   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
265*9880d681SAndroid Build Coastguard Worker   const MCExpr *BeginRef = MCSymbolRefExpr::create(Begin, Variant, Ctx),
266*9880d681SAndroid Build Coastguard Worker                *EndRef = MCSymbolRefExpr::create(End, Variant, Ctx);
267*9880d681SAndroid Build Coastguard Worker   const MCExpr *AddrDelta =
268*9880d681SAndroid Build Coastguard Worker       MCBinaryExpr::create(MCBinaryExpr::Sub, EndRef, BeginRef, Ctx);
269*9880d681SAndroid Build Coastguard Worker   int64_t Result;
270*9880d681SAndroid Build Coastguard Worker   bool Success = AddrDelta->evaluateKnownAbsolute(Result, Layout);
271*9880d681SAndroid Build Coastguard Worker   assert(Success && "failed to evaluate label difference as absolute");
272*9880d681SAndroid Build Coastguard Worker   (void)Success;
273*9880d681SAndroid Build Coastguard Worker   assert(Result >= 0 && "negative label difference requested");
274*9880d681SAndroid Build Coastguard Worker   assert(Result < UINT_MAX && "label difference greater than 2GB");
275*9880d681SAndroid Build Coastguard Worker   return unsigned(Result);
276*9880d681SAndroid Build Coastguard Worker }
277*9880d681SAndroid Build Coastguard Worker 
encodeInlineLineTable(MCAsmLayout & Layout,MCCVInlineLineTableFragment & Frag)278*9880d681SAndroid Build Coastguard Worker void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
279*9880d681SAndroid Build Coastguard Worker                                             MCCVInlineLineTableFragment &Frag) {
280*9880d681SAndroid Build Coastguard Worker   size_t LocBegin;
281*9880d681SAndroid Build Coastguard Worker   size_t LocEnd;
282*9880d681SAndroid Build Coastguard Worker   std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId);
283*9880d681SAndroid Build Coastguard Worker   for (unsigned SecondaryId : Frag.SecondaryFuncs) {
284*9880d681SAndroid Build Coastguard Worker     auto Extent = getLineExtent(SecondaryId);
285*9880d681SAndroid Build Coastguard Worker     LocBegin = std::min(LocBegin, Extent.first);
286*9880d681SAndroid Build Coastguard Worker     LocEnd = std::max(LocEnd, Extent.second);
287*9880d681SAndroid Build Coastguard Worker   }
288*9880d681SAndroid Build Coastguard Worker   if (LocBegin >= LocEnd)
289*9880d681SAndroid Build Coastguard Worker     return;
290*9880d681SAndroid Build Coastguard Worker   ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
291*9880d681SAndroid Build Coastguard Worker   if (Locs.empty())
292*9880d681SAndroid Build Coastguard Worker     return;
293*9880d681SAndroid Build Coastguard Worker 
294*9880d681SAndroid Build Coastguard Worker   SmallSet<unsigned, 8> InlinedFuncIds;
295*9880d681SAndroid Build Coastguard Worker   InlinedFuncIds.insert(Frag.SiteFuncId);
296*9880d681SAndroid Build Coastguard Worker   InlinedFuncIds.insert(Frag.SecondaryFuncs.begin(), Frag.SecondaryFuncs.end());
297*9880d681SAndroid Build Coastguard Worker 
298*9880d681SAndroid Build Coastguard Worker   // Make an artificial start location using the function start and the inlinee
299*9880d681SAndroid Build Coastguard Worker   // lines start location information. All deltas start relative to this
300*9880d681SAndroid Build Coastguard Worker   // location.
301*9880d681SAndroid Build Coastguard Worker   MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front()));
302*9880d681SAndroid Build Coastguard Worker   StartLoc.setFileNum(Frag.StartFileId);
303*9880d681SAndroid Build Coastguard Worker   StartLoc.setLine(Frag.StartLineNum);
304*9880d681SAndroid Build Coastguard Worker   const MCCVLineEntry *LastLoc = &StartLoc;
305*9880d681SAndroid Build Coastguard Worker   bool WithinFunction = true;
306*9880d681SAndroid Build Coastguard Worker 
307*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<char> &Buffer = Frag.getContents();
308*9880d681SAndroid Build Coastguard Worker   Buffer.clear(); // Clear old contents if we went through relaxation.
309*9880d681SAndroid Build Coastguard Worker   for (const MCCVLineEntry &Loc : Locs) {
310*9880d681SAndroid Build Coastguard Worker     if (!InlinedFuncIds.count(Loc.getFunctionId())) {
311*9880d681SAndroid Build Coastguard Worker       // We've hit a cv_loc not attributed to this inline call site. Use this
312*9880d681SAndroid Build Coastguard Worker       // label to end the PC range.
313*9880d681SAndroid Build Coastguard Worker       if (WithinFunction) {
314*9880d681SAndroid Build Coastguard Worker         unsigned Length =
315*9880d681SAndroid Build Coastguard Worker             computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
316*9880d681SAndroid Build Coastguard Worker         compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
317*9880d681SAndroid Build Coastguard Worker         compressAnnotation(Length, Buffer);
318*9880d681SAndroid Build Coastguard Worker       }
319*9880d681SAndroid Build Coastguard Worker       WithinFunction = false;
320*9880d681SAndroid Build Coastguard Worker       continue;
321*9880d681SAndroid Build Coastguard Worker     }
322*9880d681SAndroid Build Coastguard Worker     WithinFunction = true;
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker     if (Loc.getFileNum() != LastLoc->getFileNum()) {
325*9880d681SAndroid Build Coastguard Worker       // File ids are 1 based, and each file checksum table entry is 8 bytes
326*9880d681SAndroid Build Coastguard Worker       // long. See emitFileChecksums above.
327*9880d681SAndroid Build Coastguard Worker       unsigned FileOffset = 8 * (Loc.getFileNum() - 1);
328*9880d681SAndroid Build Coastguard Worker       compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
329*9880d681SAndroid Build Coastguard Worker       compressAnnotation(FileOffset, Buffer);
330*9880d681SAndroid Build Coastguard Worker     }
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker     int LineDelta = Loc.getLine() - LastLoc->getLine();
333*9880d681SAndroid Build Coastguard Worker     if (LineDelta == 0)
334*9880d681SAndroid Build Coastguard Worker       continue;
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker     unsigned EncodedLineDelta = encodeSignedNumber(LineDelta);
337*9880d681SAndroid Build Coastguard Worker     unsigned CodeDelta =
338*9880d681SAndroid Build Coastguard Worker         computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
339*9880d681SAndroid Build Coastguard Worker     if (CodeDelta == 0) {
340*9880d681SAndroid Build Coastguard Worker       compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
341*9880d681SAndroid Build Coastguard Worker       compressAnnotation(EncodedLineDelta, Buffer);
342*9880d681SAndroid Build Coastguard Worker     } else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) {
343*9880d681SAndroid Build Coastguard Worker       // The ChangeCodeOffsetAndLineOffset combination opcode is used when the
344*9880d681SAndroid Build Coastguard Worker       // encoded line delta uses 3 or fewer set bits and the code offset fits
345*9880d681SAndroid Build Coastguard Worker       // in one nibble.
346*9880d681SAndroid Build Coastguard Worker       unsigned Operand = (EncodedLineDelta << 4) | CodeDelta;
347*9880d681SAndroid Build Coastguard Worker       compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset,
348*9880d681SAndroid Build Coastguard Worker                          Buffer);
349*9880d681SAndroid Build Coastguard Worker       compressAnnotation(Operand, Buffer);
350*9880d681SAndroid Build Coastguard Worker     } else {
351*9880d681SAndroid Build Coastguard Worker       // Otherwise use the separate line and code deltas.
352*9880d681SAndroid Build Coastguard Worker       compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
353*9880d681SAndroid Build Coastguard Worker       compressAnnotation(EncodedLineDelta, Buffer);
354*9880d681SAndroid Build Coastguard Worker       compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer);
355*9880d681SAndroid Build Coastguard Worker       compressAnnotation(CodeDelta, Buffer);
356*9880d681SAndroid Build Coastguard Worker     }
357*9880d681SAndroid Build Coastguard Worker 
358*9880d681SAndroid Build Coastguard Worker     LastLoc = &Loc;
359*9880d681SAndroid Build Coastguard Worker   }
360*9880d681SAndroid Build Coastguard Worker 
361*9880d681SAndroid Build Coastguard Worker   assert(WithinFunction);
362*9880d681SAndroid Build Coastguard Worker 
363*9880d681SAndroid Build Coastguard Worker   unsigned EndSymLength =
364*9880d681SAndroid Build Coastguard Worker       computeLabelDiff(Layout, LastLoc->getLabel(), Frag.getFnEndSym());
365*9880d681SAndroid Build Coastguard Worker   unsigned LocAfterLength = ~0U;
366*9880d681SAndroid Build Coastguard Worker   ArrayRef<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
367*9880d681SAndroid Build Coastguard Worker   if (!LocAfter.empty()) {
368*9880d681SAndroid Build Coastguard Worker     // Only try to compute this difference if we're in the same section.
369*9880d681SAndroid Build Coastguard Worker     const MCCVLineEntry &Loc = LocAfter[0];
370*9880d681SAndroid Build Coastguard Worker     if (&Loc.getLabel()->getSection(false) ==
371*9880d681SAndroid Build Coastguard Worker         &LastLoc->getLabel()->getSection(false)) {
372*9880d681SAndroid Build Coastguard Worker       LocAfterLength =
373*9880d681SAndroid Build Coastguard Worker           computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
374*9880d681SAndroid Build Coastguard Worker     }
375*9880d681SAndroid Build Coastguard Worker   }
376*9880d681SAndroid Build Coastguard Worker 
377*9880d681SAndroid Build Coastguard Worker   compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
378*9880d681SAndroid Build Coastguard Worker   compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer);
379*9880d681SAndroid Build Coastguard Worker }
380*9880d681SAndroid Build Coastguard Worker 
encodeDefRange(MCAsmLayout & Layout,MCCVDefRangeFragment & Frag)381*9880d681SAndroid Build Coastguard Worker void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
382*9880d681SAndroid Build Coastguard Worker                                      MCCVDefRangeFragment &Frag) {
383*9880d681SAndroid Build Coastguard Worker   MCContext &Ctx = Layout.getAssembler().getContext();
384*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<char> &Contents = Frag.getContents();
385*9880d681SAndroid Build Coastguard Worker   Contents.clear();
386*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<MCFixup> &Fixups = Frag.getFixups();
387*9880d681SAndroid Build Coastguard Worker   Fixups.clear();
388*9880d681SAndroid Build Coastguard Worker   raw_svector_ostream OS(Contents);
389*9880d681SAndroid Build Coastguard Worker 
390*9880d681SAndroid Build Coastguard Worker   // Write down each range where the variable is defined.
391*9880d681SAndroid Build Coastguard Worker   for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) {
392*9880d681SAndroid Build Coastguard Worker     unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second);
393*9880d681SAndroid Build Coastguard Worker     unsigned Bias = 0;
394*9880d681SAndroid Build Coastguard Worker     // We must split the range into chunks of MaxDefRange, this is a fundamental
395*9880d681SAndroid Build Coastguard Worker     // limitation of the file format.
396*9880d681SAndroid Build Coastguard Worker     do {
397*9880d681SAndroid Build Coastguard Worker       uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize);
398*9880d681SAndroid Build Coastguard Worker 
399*9880d681SAndroid Build Coastguard Worker       const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Range.first, Ctx);
400*9880d681SAndroid Build Coastguard Worker       const MCBinaryExpr *BE =
401*9880d681SAndroid Build Coastguard Worker           MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx);
402*9880d681SAndroid Build Coastguard Worker       MCValue Res;
403*9880d681SAndroid Build Coastguard Worker       BE->evaluateAsRelocatable(Res, &Layout, /*Fixup=*/nullptr);
404*9880d681SAndroid Build Coastguard Worker 
405*9880d681SAndroid Build Coastguard Worker       // Each record begins with a 2-byte number indicating how large the record
406*9880d681SAndroid Build Coastguard Worker       // is.
407*9880d681SAndroid Build Coastguard Worker       StringRef FixedSizePortion = Frag.getFixedSizePortion();
408*9880d681SAndroid Build Coastguard Worker       // Our record is a fixed sized prefix and a LocalVariableAddrRange that we
409*9880d681SAndroid Build Coastguard Worker       // are artificially constructing.
410*9880d681SAndroid Build Coastguard Worker       size_t RecordSize =
411*9880d681SAndroid Build Coastguard Worker           FixedSizePortion.size() + sizeof(LocalVariableAddrRange);
412*9880d681SAndroid Build Coastguard Worker       // Write out the recrod size.
413*9880d681SAndroid Build Coastguard Worker       support::endian::Writer<support::little>(OS).write<uint16_t>(RecordSize);
414*9880d681SAndroid Build Coastguard Worker       // Write out the fixed size prefix.
415*9880d681SAndroid Build Coastguard Worker       OS << FixedSizePortion;
416*9880d681SAndroid Build Coastguard Worker       // Make space for a fixup that will eventually have a section relative
417*9880d681SAndroid Build Coastguard Worker       // relocation pointing at the offset where the variable becomes live.
418*9880d681SAndroid Build Coastguard Worker       Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_4));
419*9880d681SAndroid Build Coastguard Worker       Contents.resize(Contents.size() + 4); // Fixup for code start.
420*9880d681SAndroid Build Coastguard Worker       // Make space for a fixup that will record the section index for the code.
421*9880d681SAndroid Build Coastguard Worker       Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2));
422*9880d681SAndroid Build Coastguard Worker       Contents.resize(Contents.size() + 2); // Fixup for section index.
423*9880d681SAndroid Build Coastguard Worker       // Write down the range's extent.
424*9880d681SAndroid Build Coastguard Worker       support::endian::Writer<support::little>(OS).write<uint16_t>(Chunk);
425*9880d681SAndroid Build Coastguard Worker 
426*9880d681SAndroid Build Coastguard Worker       // Move on to the next range.
427*9880d681SAndroid Build Coastguard Worker       Bias += Chunk;
428*9880d681SAndroid Build Coastguard Worker       RangeSize -= Chunk;
429*9880d681SAndroid Build Coastguard Worker     } while (RangeSize > 0);
430*9880d681SAndroid Build Coastguard Worker   }
431*9880d681SAndroid Build Coastguard Worker }
432*9880d681SAndroid Build Coastguard Worker 
433*9880d681SAndroid Build Coastguard Worker //
434*9880d681SAndroid Build Coastguard Worker // This is called when an instruction is assembled into the specified section
435*9880d681SAndroid Build Coastguard Worker // and if there is information from the last .cv_loc directive that has yet to have
436*9880d681SAndroid Build Coastguard Worker // a line entry made for it is made.
437*9880d681SAndroid Build Coastguard Worker //
Make(MCObjectStreamer * MCOS)438*9880d681SAndroid Build Coastguard Worker void MCCVLineEntry::Make(MCObjectStreamer *MCOS) {
439*9880d681SAndroid Build Coastguard Worker   if (!MCOS->getContext().getCVLocSeen())
440*9880d681SAndroid Build Coastguard Worker     return;
441*9880d681SAndroid Build Coastguard Worker 
442*9880d681SAndroid Build Coastguard Worker   // Create a symbol at in the current section for use in the line entry.
443*9880d681SAndroid Build Coastguard Worker   MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
444*9880d681SAndroid Build Coastguard Worker   // Set the value of the symbol to use for the MCCVLineEntry.
445*9880d681SAndroid Build Coastguard Worker   MCOS->EmitLabel(LineSym);
446*9880d681SAndroid Build Coastguard Worker 
447*9880d681SAndroid Build Coastguard Worker   // Get the current .loc info saved in the context.
448*9880d681SAndroid Build Coastguard Worker   const MCCVLoc &CVLoc = MCOS->getContext().getCurrentCVLoc();
449*9880d681SAndroid Build Coastguard Worker 
450*9880d681SAndroid Build Coastguard Worker   // Create a (local) line entry with the symbol and the current .loc info.
451*9880d681SAndroid Build Coastguard Worker   MCCVLineEntry LineEntry(LineSym, CVLoc);
452*9880d681SAndroid Build Coastguard Worker 
453*9880d681SAndroid Build Coastguard Worker   // clear CVLocSeen saying the current .loc info is now used.
454*9880d681SAndroid Build Coastguard Worker   MCOS->getContext().clearCVLocSeen();
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker   // Add the line entry to this section's entries.
457*9880d681SAndroid Build Coastguard Worker   MCOS->getContext().getCVContext().addLineEntry(LineEntry);
458*9880d681SAndroid Build Coastguard Worker }
459