12f09f445SMaksim Panchenko //===- bolt/Core/BinaryEmitter.cpp - Emit code and data -------------------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler //
92f09f445SMaksim Panchenko // This file implements the collection of functions and classes used for
102f09f445SMaksim Panchenko // emission of code and data into object/binary file.
112f09f445SMaksim Panchenko //
12a34c753fSRafael Auler //===----------------------------------------------------------------------===//
13a34c753fSRafael Auler 
14a34c753fSRafael Auler #include "bolt/Core/BinaryEmitter.h"
15a34c753fSRafael Auler #include "bolt/Core/BinaryContext.h"
16a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h"
17a34c753fSRafael Auler #include "bolt/Core/DebugData.h"
18a34c753fSRafael Auler #include "bolt/Utils/CommandLineOpts.h"
19a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
20290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
21a34c753fSRafael Auler #include "llvm/MC/MCSection.h"
22a34c753fSRafael Auler #include "llvm/MC/MCStreamer.h"
23a34c753fSRafael Auler #include "llvm/Support/CommandLine.h"
24a34c753fSRafael Auler #include "llvm/Support/LEB128.h"
25a34c753fSRafael Auler #include "llvm/Support/SMLoc.h"
26a34c753fSRafael Auler 
27a34c753fSRafael Auler #define DEBUG_TYPE "bolt"
28a34c753fSRafael Auler 
29a34c753fSRafael Auler using namespace llvm;
30a34c753fSRafael Auler using namespace bolt;
31a34c753fSRafael Auler 
32a34c753fSRafael Auler namespace opts {
33a34c753fSRafael Auler 
34a34c753fSRafael Auler extern cl::opt<JumpTableSupportLevel> JumpTables;
35a34c753fSRafael Auler extern cl::opt<bool> PreserveBlocksAlignment;
36a34c753fSRafael Auler 
37b92436efSFangrui Song cl::opt<bool> AlignBlocks("align-blocks", cl::desc("align basic blocks"),
38a34c753fSRafael Auler                           cl::cat(BoltOptCategory));
39a34c753fSRafael Auler 
40a34c753fSRafael Auler cl::opt<MacroFusionType>
41a34c753fSRafael Auler AlignMacroOpFusion("align-macro-fusion",
42a34c753fSRafael Auler   cl::desc("fix instruction alignment for macro-fusion (x86 relocation mode)"),
43a34c753fSRafael Auler   cl::init(MFT_HOT),
44a34c753fSRafael Auler   cl::values(clEnumValN(MFT_NONE, "none",
45a34c753fSRafael Auler                "do not insert alignment no-ops for macro-fusion"),
46a34c753fSRafael Auler              clEnumValN(MFT_HOT, "hot",
47a34c753fSRafael Auler                "only insert alignment no-ops on hot execution paths (default)"),
48a34c753fSRafael Auler              clEnumValN(MFT_ALL, "all",
49a34c753fSRafael Auler                "always align instructions to allow macro-fusion")),
50a34c753fSRafael Auler   cl::ZeroOrMore,
51a34c753fSRafael Auler   cl::cat(BoltRelocCategory));
52a34c753fSRafael Auler 
53a34c753fSRafael Auler static cl::list<std::string>
54a34c753fSRafael Auler BreakFunctionNames("break-funcs",
55a34c753fSRafael Auler   cl::CommaSeparated,
56a34c753fSRafael Auler   cl::desc("list of functions to core dump on (debugging)"),
57a34c753fSRafael Auler   cl::value_desc("func1,func2,func3,..."),
58a34c753fSRafael Auler   cl::Hidden,
59a34c753fSRafael Auler   cl::cat(BoltCategory));
60a34c753fSRafael Auler 
61a34c753fSRafael Auler static cl::list<std::string>
62a34c753fSRafael Auler FunctionPadSpec("pad-funcs",
63a34c753fSRafael Auler   cl::CommaSeparated,
64a34c753fSRafael Auler   cl::desc("list of functions to pad with amount of bytes"),
65a34c753fSRafael Auler   cl::value_desc("func1:pad1,func2:pad2,func3:pad3,..."),
66a34c753fSRafael Auler   cl::Hidden,
67a34c753fSRafael Auler   cl::cat(BoltCategory));
68a34c753fSRafael Auler 
69b92436efSFangrui Song static cl::opt<bool> MarkFuncs(
70b92436efSFangrui Song     "mark-funcs",
71a34c753fSRafael Auler     cl::desc("mark function boundaries with break instruction to make "
72a34c753fSRafael Auler              "sure we accidentally don't cross them"),
73b92436efSFangrui Song     cl::ReallyHidden, cl::cat(BoltCategory));
74a34c753fSRafael Auler 
75b92436efSFangrui Song static cl::opt<bool> PrintJumpTables("print-jump-tables",
76b92436efSFangrui Song                                      cl::desc("print jump tables"), cl::Hidden,
77a34c753fSRafael Auler                                      cl::cat(BoltCategory));
78a34c753fSRafael Auler 
79a34c753fSRafael Auler static cl::opt<bool>
80a34c753fSRafael Auler X86AlignBranchBoundaryHotOnly("x86-align-branch-boundary-hot-only",
81a34c753fSRafael Auler   cl::desc("only apply branch boundary alignment in hot code"),
82a34c753fSRafael Auler   cl::init(true),
83a34c753fSRafael Auler   cl::cat(BoltOptCategory));
84a34c753fSRafael Auler 
padFunction(const BinaryFunction & Function)85a34c753fSRafael Auler size_t padFunction(const BinaryFunction &Function) {
86a34c753fSRafael Auler   static std::map<std::string, size_t> FunctionPadding;
87a34c753fSRafael Auler 
88a34c753fSRafael Auler   if (FunctionPadding.empty() && !FunctionPadSpec.empty()) {
89a34c753fSRafael Auler     for (std::string &Spec : FunctionPadSpec) {
90a34c753fSRafael Auler       size_t N = Spec.find(':');
91a34c753fSRafael Auler       if (N == std::string::npos)
92a34c753fSRafael Auler         continue;
93a34c753fSRafael Auler       std::string Name = Spec.substr(0, N);
94a34c753fSRafael Auler       size_t Padding = std::stoull(Spec.substr(N + 1));
95a34c753fSRafael Auler       FunctionPadding[Name] = Padding;
96a34c753fSRafael Auler     }
97a34c753fSRafael Auler   }
98a34c753fSRafael Auler 
99a34c753fSRafael Auler   for (auto &FPI : FunctionPadding) {
100a34c753fSRafael Auler     std::string Name = FPI.first;
101a34c753fSRafael Auler     size_t Padding = FPI.second;
1023652483cSRafael Auler     if (Function.hasNameRegex(Name))
103a34c753fSRafael Auler       return Padding;
104a34c753fSRafael Auler   }
105a34c753fSRafael Auler 
106a34c753fSRafael Auler   return 0;
107a34c753fSRafael Auler }
108a34c753fSRafael Auler 
109a34c753fSRafael Auler } // namespace opts
110a34c753fSRafael Auler 
111a34c753fSRafael Auler namespace {
112a34c753fSRafael Auler using JumpTable = bolt::JumpTable;
113a34c753fSRafael Auler 
114a34c753fSRafael Auler class BinaryEmitter {
115a34c753fSRafael Auler private:
116a34c753fSRafael Auler   BinaryEmitter(const BinaryEmitter &) = delete;
117a34c753fSRafael Auler   BinaryEmitter &operator=(const BinaryEmitter &) = delete;
118a34c753fSRafael Auler 
119a34c753fSRafael Auler   MCStreamer &Streamer;
120a34c753fSRafael Auler   BinaryContext &BC;
121a34c753fSRafael Auler 
122a34c753fSRafael Auler public:
BinaryEmitter(MCStreamer & Streamer,BinaryContext & BC)123a34c753fSRafael Auler   BinaryEmitter(MCStreamer &Streamer, BinaryContext &BC)
12440c2e0faSMaksim Panchenko       : Streamer(Streamer), BC(BC) {}
125a34c753fSRafael Auler 
126a34c753fSRafael Auler   /// Emit all code and data.
127a34c753fSRafael Auler   void emitAll(StringRef OrgSecPrefix);
128a34c753fSRafael Auler 
129a34c753fSRafael Auler   /// Emit function code. The caller is responsible for emitting function
130a34c753fSRafael Auler   /// symbol(s) and setting the section to emit the code to.
131a34c753fSRafael Auler   void emitFunctionBody(BinaryFunction &BF, bool EmitColdPart,
132a34c753fSRafael Auler                         bool EmitCodeOnly = false);
133a34c753fSRafael Auler 
134a34c753fSRafael Auler private:
135a34c753fSRafael Auler   /// Emit function code.
136a34c753fSRafael Auler   void emitFunctions();
137a34c753fSRafael Auler 
138a34c753fSRafael Auler   /// Emit a single function.
139a34c753fSRafael Auler   bool emitFunction(BinaryFunction &BF, bool EmitColdPart);
140a34c753fSRafael Auler 
141a34c753fSRafael Auler   /// Helper for emitFunctionBody to write data inside a function
142a34c753fSRafael Auler   /// (used for AArch64)
143a34c753fSRafael Auler   void emitConstantIslands(BinaryFunction &BF, bool EmitColdPart,
144a34c753fSRafael Auler                            BinaryFunction *OnBehalfOf = nullptr);
145a34c753fSRafael Auler 
146a34c753fSRafael Auler   /// Emit jump tables for the function.
147a34c753fSRafael Auler   void emitJumpTables(const BinaryFunction &BF);
148a34c753fSRafael Auler 
149a34c753fSRafael Auler   /// Emit jump table data. Callee supplies sections for the data.
150a34c753fSRafael Auler   void emitJumpTable(const JumpTable &JT, MCSection *HotSection,
151a34c753fSRafael Auler                      MCSection *ColdSection);
152a34c753fSRafael Auler 
153a34c753fSRafael Auler   void emitCFIInstruction(const MCCFIInstruction &Inst) const;
154a34c753fSRafael Auler 
155a34c753fSRafael Auler   /// Emit exception handling ranges for the function.
156a34c753fSRafael Auler   void emitLSDA(BinaryFunction &BF, bool EmitColdPart);
157a34c753fSRafael Auler 
158a34c753fSRafael Auler   /// Emit line number information corresponding to \p NewLoc. \p PrevLoc
159a34c753fSRafael Auler   /// provides a context for de-duplication of line number info.
160a34c753fSRafael Auler   /// \p FirstInstr indicates if \p NewLoc represents the first instruction
161a34c753fSRafael Auler   /// in a sequence, such as a function fragment.
162a34c753fSRafael Auler   ///
163a34c753fSRafael Auler   /// Return new current location which is either \p NewLoc or \p PrevLoc.
164a34c753fSRafael Auler   SMLoc emitLineInfo(const BinaryFunction &BF, SMLoc NewLoc, SMLoc PrevLoc,
165a34c753fSRafael Auler                      bool FirstInstr);
166a34c753fSRafael Auler 
167a34c753fSRafael Auler   /// Use \p FunctionEndSymbol to mark the end of the line info sequence.
168a34c753fSRafael Auler   /// Note that it does not automatically result in the insertion of the EOS
169a34c753fSRafael Auler   /// marker in the line table program, but provides one to the DWARF generator
170a34c753fSRafael Auler   /// when it needs it.
171a34c753fSRafael Auler   void emitLineInfoEnd(const BinaryFunction &BF, MCSymbol *FunctionEndSymbol);
172a34c753fSRafael Auler 
173a34c753fSRafael Auler   /// Emit debug line info for unprocessed functions from CUs that include
174a34c753fSRafael Auler   /// emitted functions.
175a34c753fSRafael Auler   void emitDebugLineInfoForOriginalFunctions();
176a34c753fSRafael Auler 
177a34c753fSRafael Auler   /// Emit debug line for CUs that were not modified.
178a34c753fSRafael Auler   void emitDebugLineInfoForUnprocessedCUs();
179a34c753fSRafael Auler 
180a34c753fSRafael Auler   /// Emit data sections that have code references in them.
181a34c753fSRafael Auler   void emitDataSections(StringRef OrgSecPrefix);
182a34c753fSRafael Auler };
183a34c753fSRafael Auler 
184a34c753fSRafael Auler } // anonymous namespace
185a34c753fSRafael Auler 
emitAll(StringRef OrgSecPrefix)186a34c753fSRafael Auler void BinaryEmitter::emitAll(StringRef OrgSecPrefix) {
187a34c753fSRafael Auler   Streamer.initSections(false, *BC.STI);
188a34c753fSRafael Auler 
189a34c753fSRafael Auler   if (opts::UpdateDebugSections && BC.isELF()) {
190a34c753fSRafael Auler     // Force the emission of debug line info into allocatable section to ensure
191a34c753fSRafael Auler     // RuntimeDyld will process it without ProcessAllSections flag.
192a34c753fSRafael Auler     //
193a34c753fSRafael Auler     // NB: on MachO all sections are required for execution, hence no need
194a34c753fSRafael Auler     //     to change flags/attributes.
195a34c753fSRafael Auler     MCSectionELF *ELFDwarfLineSection =
196a34c753fSRafael Auler         static_cast<MCSectionELF *>(BC.MOFI->getDwarfLineSection());
197a34c753fSRafael Auler     ELFDwarfLineSection->setFlags(ELF::SHF_ALLOC);
198a34c753fSRafael Auler   }
199a34c753fSRafael Auler 
2003652483cSRafael Auler   if (RuntimeLibrary *RtLibrary = BC.getRuntimeLibrary())
201a34c753fSRafael Auler     RtLibrary->emitBinary(BC, Streamer);
202a34c753fSRafael Auler 
203a34c753fSRafael Auler   BC.getTextSection()->setAlignment(Align(opts::AlignText));
204a34c753fSRafael Auler 
205a34c753fSRafael Auler   emitFunctions();
206a34c753fSRafael Auler 
207a34c753fSRafael Auler   if (opts::UpdateDebugSections) {
208a34c753fSRafael Auler     emitDebugLineInfoForOriginalFunctions();
209a34c753fSRafael Auler     DwarfLineTable::emit(BC, Streamer);
210a34c753fSRafael Auler   }
211a34c753fSRafael Auler 
212a34c753fSRafael Auler   emitDataSections(OrgSecPrefix);
213a34c753fSRafael Auler 
214a34c753fSRafael Auler   Streamer.emitLabel(BC.Ctx->getOrCreateSymbol("_end"));
215a34c753fSRafael Auler }
216a34c753fSRafael Auler 
emitFunctions()217a34c753fSRafael Auler void BinaryEmitter::emitFunctions() {
218a34c753fSRafael Auler   auto emit = [&](const std::vector<BinaryFunction *> &Functions) {
219a34c753fSRafael Auler     const bool HasProfile = BC.NumProfiledFuncs > 0;
220a34c753fSRafael Auler     const bool OriginalAllowAutoPadding = Streamer.getAllowAutoPadding();
221a34c753fSRafael Auler     for (BinaryFunction *Function : Functions) {
2223652483cSRafael Auler       if (!BC.shouldEmit(*Function))
223a34c753fSRafael Auler         continue;
224a34c753fSRafael Auler 
225a34c753fSRafael Auler       LLVM_DEBUG(dbgs() << "BOLT: generating code for function \"" << *Function
226a34c753fSRafael Auler                         << "\" : " << Function->getFunctionNumber() << '\n');
227a34c753fSRafael Auler 
228a34c753fSRafael Auler       // Was any part of the function emitted.
229a34c753fSRafael Auler       bool Emitted = false;
230a34c753fSRafael Auler 
231a34c753fSRafael Auler       // Turn off Intel JCC Erratum mitigation for cold code if requested
232a34c753fSRafael Auler       if (HasProfile && opts::X86AlignBranchBoundaryHotOnly &&
233a34c753fSRafael Auler           !Function->hasValidProfile())
234a34c753fSRafael Auler         Streamer.setAllowAutoPadding(false);
235a34c753fSRafael Auler 
236a34c753fSRafael Auler       Emitted |= emitFunction(*Function, /*EmitColdPart=*/false);
237a34c753fSRafael Auler 
238a34c753fSRafael Auler       if (Function->isSplit()) {
239a34c753fSRafael Auler         if (opts::X86AlignBranchBoundaryHotOnly)
240a34c753fSRafael Auler           Streamer.setAllowAutoPadding(false);
241a34c753fSRafael Auler         Emitted |= emitFunction(*Function, /*EmitColdPart=*/true);
242a34c753fSRafael Auler       }
243a34c753fSRafael Auler       Streamer.setAllowAutoPadding(OriginalAllowAutoPadding);
244a34c753fSRafael Auler 
245a34c753fSRafael Auler       if (Emitted)
246a34c753fSRafael Auler         Function->setEmitted(/*KeepCFG=*/opts::PrintCacheMetrics);
247a34c753fSRafael Auler     }
248a34c753fSRafael Auler   };
249a34c753fSRafael Auler 
250a34c753fSRafael Auler   // Mark the start of hot text.
251a34c753fSRafael Auler   if (opts::HotText) {
252adf4142fSFangrui Song     Streamer.switchSection(BC.getTextSection());
253a34c753fSRafael Auler     Streamer.emitLabel(BC.getHotTextStartSymbol());
254a34c753fSRafael Auler   }
255a34c753fSRafael Auler 
256a34c753fSRafael Auler   // Emit functions in sorted order.
257a34c753fSRafael Auler   std::vector<BinaryFunction *> SortedFunctions = BC.getSortedFunctions();
258a34c753fSRafael Auler   emit(SortedFunctions);
259a34c753fSRafael Auler 
260a34c753fSRafael Auler   // Emit functions added by BOLT.
261a34c753fSRafael Auler   emit(BC.getInjectedBinaryFunctions());
262a34c753fSRafael Auler 
263a34c753fSRafael Auler   // Mark the end of hot text.
264a34c753fSRafael Auler   if (opts::HotText) {
265adf4142fSFangrui Song     Streamer.switchSection(BC.getTextSection());
266a34c753fSRafael Auler     Streamer.emitLabel(BC.getHotTextEndSymbol());
267a34c753fSRafael Auler   }
268a34c753fSRafael Auler }
269a34c753fSRafael Auler 
emitFunction(BinaryFunction & Function,bool EmitColdPart)270a34c753fSRafael Auler bool BinaryEmitter::emitFunction(BinaryFunction &Function, bool EmitColdPart) {
271fed958c6SVladislav Khmelevsky   if (Function.size() == 0 && !Function.hasIslandsInfo())
272a34c753fSRafael Auler     return false;
273a34c753fSRafael Auler 
274a34c753fSRafael Auler   if (Function.getState() == BinaryFunction::State::Empty)
275a34c753fSRafael Auler     return false;
276a34c753fSRafael Auler 
277a34c753fSRafael Auler   MCSection *Section =
278a34c753fSRafael Auler       BC.getCodeSection(EmitColdPart ? Function.getColdCodeSectionName()
279a34c753fSRafael Auler                                      : Function.getCodeSectionName());
280adf4142fSFangrui Song   Streamer.switchSection(Section);
281a34c753fSRafael Auler   Section->setHasInstructions(true);
282a34c753fSRafael Auler   BC.Ctx->addGenDwarfSection(Section);
283a34c753fSRafael Auler 
284a34c753fSRafael Auler   if (BC.HasRelocations) {
2858ab69baaSVladislav Khmelevsky     // Set section alignment to at least maximum possible object alignment.
2868ab69baaSVladislav Khmelevsky     // We need this to support LongJmp and other passes that calculates
2878ab69baaSVladislav Khmelevsky     // tentative layout.
2888ab69baaSVladislav Khmelevsky     if (Section->getAlignment() < opts::AlignFunctions)
2898ab69baaSVladislav Khmelevsky       Section->setAlignment(Align(opts::AlignFunctions));
2908ab69baaSVladislav Khmelevsky 
291a34c753fSRafael Auler     Streamer.emitCodeAlignment(BinaryFunction::MinAlign, &*BC.STI);
29240c2e0faSMaksim Panchenko     uint16_t MaxAlignBytes = EmitColdPart ? Function.getMaxColdAlignmentBytes()
293a34c753fSRafael Auler                                           : Function.getMaxAlignmentBytes();
294a34c753fSRafael Auler     if (MaxAlignBytes > 0)
295a34c753fSRafael Auler       Streamer.emitCodeAlignment(Function.getAlignment(), &*BC.STI,
296a34c753fSRafael Auler                                  MaxAlignBytes);
297a34c753fSRafael Auler   } else {
298a34c753fSRafael Auler     Streamer.emitCodeAlignment(Function.getAlignment(), &*BC.STI);
299a34c753fSRafael Auler   }
300a34c753fSRafael Auler 
301a34c753fSRafael Auler   MCContext &Context = Streamer.getContext();
302a34c753fSRafael Auler   const MCAsmInfo *MAI = Context.getAsmInfo();
303a34c753fSRafael Auler 
304a34c753fSRafael Auler   MCSymbol *StartSymbol = nullptr;
305a34c753fSRafael Auler 
306a34c753fSRafael Auler   // Emit all symbols associated with the main function entry.
307a34c753fSRafael Auler   if (!EmitColdPart) {
308a34c753fSRafael Auler     StartSymbol = Function.getSymbol();
309a34c753fSRafael Auler     for (MCSymbol *Symbol : Function.getSymbols()) {
310a34c753fSRafael Auler       Streamer.emitSymbolAttribute(Symbol, MCSA_ELF_TypeFunction);
311a34c753fSRafael Auler       Streamer.emitLabel(Symbol);
312a34c753fSRafael Auler     }
313a34c753fSRafael Auler   } else {
314a34c753fSRafael Auler     StartSymbol = Function.getColdSymbol();
315a34c753fSRafael Auler     Streamer.emitSymbolAttribute(StartSymbol, MCSA_ELF_TypeFunction);
316a34c753fSRafael Auler     Streamer.emitLabel(StartSymbol);
317a34c753fSRafael Auler   }
318a34c753fSRafael Auler 
319a34c753fSRafael Auler   // Emit CFI start
320a34c753fSRafael Auler   if (Function.hasCFI()) {
321a34c753fSRafael Auler     Streamer.emitCFIStartProc(/*IsSimple=*/false);
322986e5dedSMaksim Panchenko     if (Function.getPersonalityFunction() != nullptr)
323a34c753fSRafael Auler       Streamer.emitCFIPersonality(Function.getPersonalityFunction(),
324a34c753fSRafael Auler                                   Function.getPersonalityEncoding());
325a34c753fSRafael Auler     MCSymbol *LSDASymbol =
326a34c753fSRafael Auler         EmitColdPart ? Function.getColdLSDASymbol() : Function.getLSDASymbol();
3273652483cSRafael Auler     if (LSDASymbol)
328a34c753fSRafael Auler       Streamer.emitCFILsda(LSDASymbol, BC.LSDAEncoding);
3293652483cSRafael Auler     else
330a34c753fSRafael Auler       Streamer.emitCFILsda(0, dwarf::DW_EH_PE_omit);
331a34c753fSRafael Auler     // Emit CFI instructions relative to the CIE
332a34c753fSRafael Auler     for (const MCCFIInstruction &CFIInstr : Function.cie()) {
333a34c753fSRafael Auler       // Only write CIE CFI insns that LLVM will not already emit
334a34c753fSRafael Auler       const std::vector<MCCFIInstruction> &FrameInstrs =
335a34c753fSRafael Auler           MAI->getInitialFrameState();
336d2c87699SAmir Ayupov       if (!llvm::is_contained(FrameInstrs, CFIInstr))
337a34c753fSRafael Auler         emitCFIInstruction(CFIInstr);
338a34c753fSRafael Auler     }
339a34c753fSRafael Auler   }
340a34c753fSRafael Auler 
341a34c753fSRafael Auler   assert((Function.empty() || !(*Function.begin()).isCold()) &&
342a34c753fSRafael Auler          "first basic block should never be cold");
343a34c753fSRafael Auler 
344a34c753fSRafael Auler   // Emit UD2 at the beginning if requested by user.
345a34c753fSRafael Auler   if (!opts::BreakFunctionNames.empty()) {
346a34c753fSRafael Auler     for (std::string &Name : opts::BreakFunctionNames) {
347a34c753fSRafael Auler       if (Function.hasNameRegex(Name)) {
348a34c753fSRafael Auler         Streamer.emitIntValue(0x0B0F, 2); // UD2: 0F 0B
349a34c753fSRafael Auler         break;
350a34c753fSRafael Auler       }
351a34c753fSRafael Auler     }
352a34c753fSRafael Auler   }
353a34c753fSRafael Auler 
354a34c753fSRafael Auler   // Emit code.
355a34c753fSRafael Auler   emitFunctionBody(Function, EmitColdPart, /*EmitCodeOnly=*/false);
356a34c753fSRafael Auler 
357a34c753fSRafael Auler   // Emit padding if requested.
358a34c753fSRafael Auler   if (size_t Padding = opts::padFunction(Function)) {
359a34c753fSRafael Auler     LLVM_DEBUG(dbgs() << "BOLT-DEBUG: padding function " << Function << " with "
360a34c753fSRafael Auler                       << Padding << " bytes\n");
361a34c753fSRafael Auler     Streamer.emitFill(Padding, MAI->getTextAlignFillValue());
362a34c753fSRafael Auler   }
363a34c753fSRafael Auler 
3643652483cSRafael Auler   if (opts::MarkFuncs)
365a34c753fSRafael Auler     Streamer.emitIntValue(BC.MIB->getTrapFillValue(), 1);
366a34c753fSRafael Auler 
367a34c753fSRafael Auler   // Emit CFI end
368a34c753fSRafael Auler   if (Function.hasCFI())
369a34c753fSRafael Auler     Streamer.emitCFIEndProc();
370a34c753fSRafael Auler 
371a34c753fSRafael Auler   MCSymbol *EndSymbol = EmitColdPart ? Function.getFunctionColdEndLabel()
372a34c753fSRafael Auler                                      : Function.getFunctionEndLabel();
373a34c753fSRafael Auler   Streamer.emitLabel(EndSymbol);
374a34c753fSRafael Auler 
375a34c753fSRafael Auler   if (MAI->hasDotTypeDotSizeDirective()) {
376a34c753fSRafael Auler     const MCExpr *SizeExpr = MCBinaryExpr::createSub(
377a34c753fSRafael Auler         MCSymbolRefExpr::create(EndSymbol, Context),
378a34c753fSRafael Auler         MCSymbolRefExpr::create(StartSymbol, Context), Context);
379a34c753fSRafael Auler     Streamer.emitELFSize(StartSymbol, SizeExpr);
380a34c753fSRafael Auler   }
381a34c753fSRafael Auler 
382a34c753fSRafael Auler   if (opts::UpdateDebugSections && Function.getDWARFUnit())
383a34c753fSRafael Auler     emitLineInfoEnd(Function, EndSymbol);
384a34c753fSRafael Auler 
385a34c753fSRafael Auler   // Exception handling info for the function.
386a34c753fSRafael Auler   emitLSDA(Function, EmitColdPart);
387a34c753fSRafael Auler 
388a34c753fSRafael Auler   if (!EmitColdPart && opts::JumpTables > JTS_NONE)
389a34c753fSRafael Auler     emitJumpTables(Function);
390a34c753fSRafael Auler 
391a34c753fSRafael Auler   return true;
392a34c753fSRafael Auler }
393a34c753fSRafael Auler 
emitFunctionBody(BinaryFunction & BF,bool EmitColdPart,bool EmitCodeOnly)394a34c753fSRafael Auler void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, bool EmitColdPart,
395a34c753fSRafael Auler                                      bool EmitCodeOnly) {
396a34c753fSRafael Auler   if (!EmitCodeOnly && EmitColdPart && BF.hasConstantIsland())
397a34c753fSRafael Auler     BF.duplicateConstantIslands();
398a34c753fSRafael Auler 
399a34c753fSRafael Auler   // Track the first emitted instruction with debug info.
400a34c753fSRafael Auler   bool FirstInstr = true;
401*8477bc67SFabian Parzefall   for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
402a34c753fSRafael Auler     if (EmitColdPart != BB->isCold())
403a34c753fSRafael Auler       continue;
404a34c753fSRafael Auler 
40540c2e0faSMaksim Panchenko     if ((opts::AlignBlocks || opts::PreserveBlocksAlignment) &&
406986e5dedSMaksim Panchenko         BB->getAlignment() > 1)
407a34c753fSRafael Auler       Streamer.emitCodeAlignment(BB->getAlignment(), &*BC.STI,
408a34c753fSRafael Auler                                  BB->getAlignmentMaxBytes());
409a34c753fSRafael Auler     Streamer.emitLabel(BB->getLabel());
410a34c753fSRafael Auler     if (!EmitCodeOnly) {
4113652483cSRafael Auler       if (MCSymbol *EntrySymbol = BF.getSecondaryEntryPointSymbol(*BB))
412a34c753fSRafael Auler         Streamer.emitLabel(EntrySymbol);
413a34c753fSRafael Auler     }
414a34c753fSRafael Auler 
415a34c753fSRafael Auler     // Check if special alignment for macro-fusion is needed.
416a34c753fSRafael Auler     bool MayNeedMacroFusionAlignment =
417a34c753fSRafael Auler         (opts::AlignMacroOpFusion == MFT_ALL) ||
41840c2e0faSMaksim Panchenko         (opts::AlignMacroOpFusion == MFT_HOT && BB->getKnownExecutionCount());
419a34c753fSRafael Auler     BinaryBasicBlock::const_iterator MacroFusionPair;
420a34c753fSRafael Auler     if (MayNeedMacroFusionAlignment) {
421a34c753fSRafael Auler       MacroFusionPair = BB->getMacroOpFusionPair();
422a34c753fSRafael Auler       if (MacroFusionPair == BB->end())
423a34c753fSRafael Auler         MayNeedMacroFusionAlignment = false;
424a34c753fSRafael Auler     }
425a34c753fSRafael Auler 
426a34c753fSRafael Auler     SMLoc LastLocSeen;
427a34c753fSRafael Auler     // Remember if the last instruction emitted was a prefix.
428a34c753fSRafael Auler     bool LastIsPrefix = false;
429a34c753fSRafael Auler     for (auto I = BB->begin(), E = BB->end(); I != E; ++I) {
430a34c753fSRafael Auler       MCInst &Instr = *I;
431a34c753fSRafael Auler 
432a34c753fSRafael Auler       if (EmitCodeOnly && BC.MIB->isPseudo(Instr))
433a34c753fSRafael Auler         continue;
434a34c753fSRafael Auler 
435a34c753fSRafael Auler       // Handle pseudo instructions.
436a34c753fSRafael Auler       if (BC.MIB->isEHLabel(Instr)) {
437a34c753fSRafael Auler         const MCSymbol *Label = BC.MIB->getTargetSymbol(Instr);
438a34c753fSRafael Auler         assert(Instr.getNumOperands() >= 1 && Label &&
439a34c753fSRafael Auler                "bad EH_LABEL instruction");
440a34c753fSRafael Auler         Streamer.emitLabel(const_cast<MCSymbol *>(Label));
441a34c753fSRafael Auler         continue;
442a34c753fSRafael Auler       }
443a34c753fSRafael Auler       if (BC.MIB->isCFI(Instr)) {
444a34c753fSRafael Auler         emitCFIInstruction(*BF.getCFIFor(Instr));
445a34c753fSRafael Auler         continue;
446a34c753fSRafael Auler       }
447a34c753fSRafael Auler 
448a34c753fSRafael Auler       // Handle macro-fusion alignment. If we emitted a prefix as
449a34c753fSRafael Auler       // the last instruction, we should've already emitted the associated
450a34c753fSRafael Auler       // alignment hint, so don't emit it twice.
45140c2e0faSMaksim Panchenko       if (MayNeedMacroFusionAlignment && !LastIsPrefix &&
45240c2e0faSMaksim Panchenko           I == MacroFusionPair) {
453a34c753fSRafael Auler         // This assumes the second instruction in the macro-op pair will get
454a34c753fSRafael Auler         // assigned to its own MCRelaxableFragment. Since all JCC instructions
455a34c753fSRafael Auler         // are relaxable, we should be safe.
456a34c753fSRafael Auler       }
457a34c753fSRafael Auler 
458a34c753fSRafael Auler       if (!EmitCodeOnly && opts::UpdateDebugSections && BF.getDWARFUnit()) {
459a34c753fSRafael Auler         LastLocSeen = emitLineInfo(BF, Instr.getLoc(), LastLocSeen, FirstInstr);
460a34c753fSRafael Auler         FirstInstr = false;
461a34c753fSRafael Auler       }
462a34c753fSRafael Auler 
463a34c753fSRafael Auler       // Prepare to tag this location with a label if we need to keep track of
464a34c753fSRafael Auler       // the location of calls/returns for BOLT address translation maps
465a34c753fSRafael Auler       if (!EmitCodeOnly && BF.requiresAddressTranslation() &&
466a9cd49d5SAmir Ayupov           BC.MIB->getOffset(Instr)) {
467a9cd49d5SAmir Ayupov         const uint32_t Offset = *BC.MIB->getOffset(Instr);
468a34c753fSRafael Auler         MCSymbol *LocSym = BC.Ctx->createTempSymbol();
469a34c753fSRafael Auler         Streamer.emitLabel(LocSym);
470a34c753fSRafael Auler         BB->getLocSyms().emplace_back(Offset, LocSym);
471a34c753fSRafael Auler       }
472a34c753fSRafael Auler 
473a34c753fSRafael Auler       Streamer.emitInstruction(Instr, *BC.STI);
474a34c753fSRafael Auler       LastIsPrefix = BC.MIB->isPrefix(Instr);
475a34c753fSRafael Auler     }
476a34c753fSRafael Auler   }
477a34c753fSRafael Auler 
478a34c753fSRafael Auler   if (!EmitCodeOnly)
479a34c753fSRafael Auler     emitConstantIslands(BF, EmitColdPart);
480a34c753fSRafael Auler }
481a34c753fSRafael Auler 
emitConstantIslands(BinaryFunction & BF,bool EmitColdPart,BinaryFunction * OnBehalfOf)482a34c753fSRafael Auler void BinaryEmitter::emitConstantIslands(BinaryFunction &BF, bool EmitColdPart,
483a34c753fSRafael Auler                                         BinaryFunction *OnBehalfOf) {
484a34c753fSRafael Auler   if (!BF.hasIslandsInfo())
485a34c753fSRafael Auler     return;
486a34c753fSRafael Auler 
487a34c753fSRafael Auler   BinaryFunction::IslandInfo &Islands = BF.getIslandInfo();
488a34c753fSRafael Auler   if (Islands.DataOffsets.empty() && Islands.Dependency.empty())
489a34c753fSRafael Auler     return;
490a34c753fSRafael Auler 
491af9bdcfcSVladislav Khmelevsky   // AArch64 requires CI to be aligned to 8 bytes due to access instructions
492af9bdcfcSVladislav Khmelevsky   // restrictions. E.g. the ldr with imm, where imm must be aligned to 8 bytes.
493af9bdcfcSVladislav Khmelevsky   const uint16_t Alignment = OnBehalfOf
494af9bdcfcSVladislav Khmelevsky                                  ? OnBehalfOf->getConstantIslandAlignment()
495af9bdcfcSVladislav Khmelevsky                                  : BF.getConstantIslandAlignment();
496af9bdcfcSVladislav Khmelevsky   Streamer.emitCodeAlignment(Alignment, &*BC.STI);
497af9bdcfcSVladislav Khmelevsky 
498a34c753fSRafael Auler   if (!OnBehalfOf) {
499a34c753fSRafael Auler     if (!EmitColdPart)
500a34c753fSRafael Auler       Streamer.emitLabel(BF.getFunctionConstantIslandLabel());
501a34c753fSRafael Auler     else
502a34c753fSRafael Auler       Streamer.emitLabel(BF.getFunctionColdConstantIslandLabel());
503a34c753fSRafael Auler   }
504a34c753fSRafael Auler 
505a34c753fSRafael Auler   assert((!OnBehalfOf || Islands.Proxies[OnBehalfOf].size() > 0) &&
506a34c753fSRafael Auler          "spurious OnBehalfOf constant island emission");
507a34c753fSRafael Auler 
508a34c753fSRafael Auler   assert(!BF.isInjected() &&
509a34c753fSRafael Auler          "injected functions should not have constant islands");
510a34c753fSRafael Auler   // Raw contents of the function.
511a34c753fSRafael Auler   StringRef SectionContents = BF.getOriginSection()->getContents();
512a34c753fSRafael Auler 
513a34c753fSRafael Auler   // Raw contents of the function.
51440c2e0faSMaksim Panchenko   StringRef FunctionContents = SectionContents.substr(
51540c2e0faSMaksim Panchenko       BF.getAddress() - BF.getOriginSection()->getAddress(), BF.getMaxSize());
516a34c753fSRafael Auler 
517a34c753fSRafael Auler   if (opts::Verbosity && !OnBehalfOf)
518a34c753fSRafael Auler     outs() << "BOLT-INFO: emitting constant island for function " << BF << "\n";
519a34c753fSRafael Auler 
520a34c753fSRafael Auler   // We split the island into smaller blocks and output labels between them.
521a34c753fSRafael Auler   auto IS = Islands.Offsets.begin();
522a34c753fSRafael Auler   for (auto DataIter = Islands.DataOffsets.begin();
52340c2e0faSMaksim Panchenko        DataIter != Islands.DataOffsets.end(); ++DataIter) {
524a34c753fSRafael Auler     uint64_t FunctionOffset = *DataIter;
525a34c753fSRafael Auler     uint64_t EndOffset = 0ULL;
526a34c753fSRafael Auler 
527a34c753fSRafael Auler     // Determine size of this data chunk
528a34c753fSRafael Auler     auto NextData = std::next(DataIter);
529a34c753fSRafael Auler     auto CodeIter = Islands.CodeOffsets.lower_bound(*DataIter);
530a34c753fSRafael Auler     if (CodeIter == Islands.CodeOffsets.end() &&
531986e5dedSMaksim Panchenko         NextData == Islands.DataOffsets.end())
532a34c753fSRafael Auler       EndOffset = BF.getMaxSize();
533986e5dedSMaksim Panchenko     else if (CodeIter == Islands.CodeOffsets.end())
534a34c753fSRafael Auler       EndOffset = *NextData;
535986e5dedSMaksim Panchenko     else if (NextData == Islands.DataOffsets.end())
536a34c753fSRafael Auler       EndOffset = *CodeIter;
537986e5dedSMaksim Panchenko     else
538a34c753fSRafael Auler       EndOffset = (*CodeIter > *NextData) ? *NextData : *CodeIter;
539a34c753fSRafael Auler 
540a34c753fSRafael Auler     if (FunctionOffset == EndOffset)
541a34c753fSRafael Auler       continue; // Size is zero, nothing to emit
542a34c753fSRafael Auler 
543a34c753fSRafael Auler     auto emitCI = [&](uint64_t &FunctionOffset, uint64_t EndOffset) {
544a34c753fSRafael Auler       if (FunctionOffset >= EndOffset)
545a34c753fSRafael Auler         return;
546a34c753fSRafael Auler 
547a34c753fSRafael Auler       for (auto It = Islands.Relocations.lower_bound(FunctionOffset);
548a34c753fSRafael Auler            It != Islands.Relocations.end(); ++It) {
549a34c753fSRafael Auler         if (It->first >= EndOffset)
550a34c753fSRafael Auler           break;
551a34c753fSRafael Auler 
552a34c753fSRafael Auler         const Relocation &Relocation = It->second;
553a34c753fSRafael Auler         if (FunctionOffset < Relocation.Offset) {
554a34c753fSRafael Auler           Streamer.emitBytes(
555a34c753fSRafael Auler               FunctionContents.slice(FunctionOffset, Relocation.Offset));
556a34c753fSRafael Auler           FunctionOffset = Relocation.Offset;
557a34c753fSRafael Auler         }
558a34c753fSRafael Auler 
559a34c753fSRafael Auler         LLVM_DEBUG(
560a34c753fSRafael Auler             dbgs() << "BOLT-DEBUG: emitting constant island relocation"
561a34c753fSRafael Auler                    << " for " << BF << " at offset 0x"
562a34c753fSRafael Auler                    << Twine::utohexstr(Relocation.Offset) << " with size "
563a34c753fSRafael Auler                    << Relocation::getSizeForType(Relocation.Type) << '\n');
564a34c753fSRafael Auler 
565a34c753fSRafael Auler         FunctionOffset += Relocation.emit(&Streamer);
566a34c753fSRafael Auler       }
567a34c753fSRafael Auler 
568a34c753fSRafael Auler       assert(FunctionOffset <= EndOffset && "overflow error");
569a34c753fSRafael Auler       if (FunctionOffset < EndOffset) {
570a34c753fSRafael Auler         Streamer.emitBytes(FunctionContents.slice(FunctionOffset, EndOffset));
571a34c753fSRafael Auler         FunctionOffset = EndOffset;
572a34c753fSRafael Auler       }
573a34c753fSRafael Auler     };
574a34c753fSRafael Auler 
575a34c753fSRafael Auler     // Emit labels, relocs and data
576a34c753fSRafael Auler     while (IS != Islands.Offsets.end() && IS->first < EndOffset) {
577a34c753fSRafael Auler       auto NextLabelOffset =
578a34c753fSRafael Auler           IS == Islands.Offsets.end() ? EndOffset : IS->first;
579a34c753fSRafael Auler       auto NextStop = std::min(NextLabelOffset, EndOffset);
580a34c753fSRafael Auler       assert(NextStop <= EndOffset && "internal overflow error");
581a34c753fSRafael Auler       emitCI(FunctionOffset, NextStop);
582a34c753fSRafael Auler       if (IS != Islands.Offsets.end() && FunctionOffset == IS->first) {
583a34c753fSRafael Auler         // This is a slightly complex code to decide which label to emit. We
584a34c753fSRafael Auler         // have 4 cases to handle: regular symbol, cold symbol, regular or cold
585a34c753fSRafael Auler         // symbol being emitted on behalf of an external function.
586a34c753fSRafael Auler         if (!OnBehalfOf) {
587a34c753fSRafael Auler           if (!EmitColdPart) {
588a34c753fSRafael Auler             LLVM_DEBUG(dbgs() << "BOLT-DEBUG: emitted label "
589a34c753fSRafael Auler                               << IS->second->getName() << " at offset 0x"
590a34c753fSRafael Auler                               << Twine::utohexstr(IS->first) << '\n');
591a34c753fSRafael Auler             if (IS->second->isUndefined())
592a34c753fSRafael Auler               Streamer.emitLabel(IS->second);
593a34c753fSRafael Auler             else
594a34c753fSRafael Auler               assert(BF.hasName(std::string(IS->second->getName())));
595a34c753fSRafael Auler           } else if (Islands.ColdSymbols.count(IS->second) != 0) {
596a34c753fSRafael Auler             LLVM_DEBUG(dbgs()
597a34c753fSRafael Auler                        << "BOLT-DEBUG: emitted label "
598a34c753fSRafael Auler                        << Islands.ColdSymbols[IS->second]->getName() << '\n');
599a34c753fSRafael Auler             if (Islands.ColdSymbols[IS->second]->isUndefined())
600a34c753fSRafael Auler               Streamer.emitLabel(Islands.ColdSymbols[IS->second]);
601a34c753fSRafael Auler           }
602a34c753fSRafael Auler         } else {
603a34c753fSRafael Auler           if (!EmitColdPart) {
604a34c753fSRafael Auler             if (MCSymbol *Sym = Islands.Proxies[OnBehalfOf][IS->second]) {
605a34c753fSRafael Auler               LLVM_DEBUG(dbgs() << "BOLT-DEBUG: emitted label "
606a34c753fSRafael Auler                                 << Sym->getName() << '\n');
607a34c753fSRafael Auler               Streamer.emitLabel(Sym);
608a34c753fSRafael Auler             }
609a34c753fSRafael Auler           } else if (MCSymbol *Sym =
610a34c753fSRafael Auler                          Islands.ColdProxies[OnBehalfOf][IS->second]) {
611a34c753fSRafael Auler             LLVM_DEBUG(dbgs() << "BOLT-DEBUG: emitted label " << Sym->getName()
612a34c753fSRafael Auler                               << '\n');
613a34c753fSRafael Auler             Streamer.emitLabel(Sym);
614a34c753fSRafael Auler           }
615a34c753fSRafael Auler         }
616a34c753fSRafael Auler         ++IS;
617a34c753fSRafael Auler       }
618a34c753fSRafael Auler     }
619a34c753fSRafael Auler     assert(FunctionOffset <= EndOffset && "overflow error");
620a34c753fSRafael Auler     emitCI(FunctionOffset, EndOffset);
621a34c753fSRafael Auler   }
622a34c753fSRafael Auler   assert(IS == Islands.Offsets.end() && "some symbols were not emitted!");
623a34c753fSRafael Auler 
624a34c753fSRafael Auler   if (OnBehalfOf)
625a34c753fSRafael Auler     return;
626a34c753fSRafael Auler   // Now emit constant islands from other functions that we may have used in
627a34c753fSRafael Auler   // this function.
6283652483cSRafael Auler   for (BinaryFunction *ExternalFunc : Islands.Dependency)
629a34c753fSRafael Auler     emitConstantIslands(*ExternalFunc, EmitColdPart, &BF);
630a34c753fSRafael Auler }
631a34c753fSRafael Auler 
emitLineInfo(const BinaryFunction & BF,SMLoc NewLoc,SMLoc PrevLoc,bool FirstInstr)632a34c753fSRafael Auler SMLoc BinaryEmitter::emitLineInfo(const BinaryFunction &BF, SMLoc NewLoc,
633a34c753fSRafael Auler                                   SMLoc PrevLoc, bool FirstInstr) {
634a34c753fSRafael Auler   DWARFUnit *FunctionCU = BF.getDWARFUnit();
635a34c753fSRafael Auler   const DWARFDebugLine::LineTable *FunctionLineTable = BF.getDWARFLineTable();
636a34c753fSRafael Auler   assert(FunctionCU && "cannot emit line info for function without CU");
637a34c753fSRafael Auler 
638a34c753fSRafael Auler   DebugLineTableRowRef RowReference = DebugLineTableRowRef::fromSMLoc(NewLoc);
639a34c753fSRafael Auler 
640a34c753fSRafael Auler   // Check if no new line info needs to be emitted.
641a34c753fSRafael Auler   if (RowReference == DebugLineTableRowRef::NULL_ROW ||
642a34c753fSRafael Auler       NewLoc.getPointer() == PrevLoc.getPointer())
643a34c753fSRafael Auler     return PrevLoc;
644a34c753fSRafael Auler 
645a34c753fSRafael Auler   unsigned CurrentFilenum = 0;
646a34c753fSRafael Auler   const DWARFDebugLine::LineTable *CurrentLineTable = FunctionLineTable;
647a34c753fSRafael Auler 
648a34c753fSRafael Auler   // If the CU id from the current instruction location does not
649a34c753fSRafael Auler   // match the CU id from the current function, it means that we
650a34c753fSRafael Auler   // have come across some inlined code.  We must look up the CU
651a34c753fSRafael Auler   // for the instruction's original function and get the line table
652a34c753fSRafael Auler   // from that.
653a34c753fSRafael Auler   const uint64_t FunctionUnitIndex = FunctionCU->getOffset();
654a34c753fSRafael Auler   const uint32_t CurrentUnitIndex = RowReference.DwCompileUnitIndex;
655a34c753fSRafael Auler   if (CurrentUnitIndex != FunctionUnitIndex) {
656a34c753fSRafael Auler     CurrentLineTable = BC.DwCtx->getLineTableForUnit(
657a34c753fSRafael Auler         BC.DwCtx->getCompileUnitForOffset(CurrentUnitIndex));
658a34c753fSRafael Auler     // Add filename from the inlined function to the current CU.
65940c2e0faSMaksim Panchenko     CurrentFilenum = BC.addDebugFilenameToUnit(
66040c2e0faSMaksim Panchenko         FunctionUnitIndex, CurrentUnitIndex,
661a34c753fSRafael Auler         CurrentLineTable->Rows[RowReference.RowIndex - 1].File);
662a34c753fSRafael Auler   }
663a34c753fSRafael Auler 
664a34c753fSRafael Auler   const DWARFDebugLine::Row &CurrentRow =
665a34c753fSRafael Auler       CurrentLineTable->Rows[RowReference.RowIndex - 1];
666a34c753fSRafael Auler   if (!CurrentFilenum)
667a34c753fSRafael Auler     CurrentFilenum = CurrentRow.File;
668a34c753fSRafael Auler 
669a34c753fSRafael Auler   unsigned Flags = (DWARF2_FLAG_IS_STMT * CurrentRow.IsStmt) |
670a34c753fSRafael Auler                    (DWARF2_FLAG_BASIC_BLOCK * CurrentRow.BasicBlock) |
671a34c753fSRafael Auler                    (DWARF2_FLAG_PROLOGUE_END * CurrentRow.PrologueEnd) |
672a34c753fSRafael Auler                    (DWARF2_FLAG_EPILOGUE_BEGIN * CurrentRow.EpilogueBegin);
673a34c753fSRafael Auler 
674a34c753fSRafael Auler   // Always emit is_stmt at the beginning of function fragment.
675a34c753fSRafael Auler   if (FirstInstr)
676a34c753fSRafael Auler     Flags |= DWARF2_FLAG_IS_STMT;
677a34c753fSRafael Auler 
67840c2e0faSMaksim Panchenko   BC.Ctx->setCurrentDwarfLoc(CurrentFilenum, CurrentRow.Line, CurrentRow.Column,
67940c2e0faSMaksim Panchenko                              Flags, CurrentRow.Isa, CurrentRow.Discriminator);
680a34c753fSRafael Auler   const MCDwarfLoc &DwarfLoc = BC.Ctx->getCurrentDwarfLoc();
681a34c753fSRafael Auler   BC.Ctx->clearDwarfLocSeen();
682a34c753fSRafael Auler 
683a34c753fSRafael Auler   MCSymbol *LineSym = BC.Ctx->createTempSymbol();
684a34c753fSRafael Auler   Streamer.emitLabel(LineSym);
685a34c753fSRafael Auler 
686a34c753fSRafael Auler   BC.getDwarfLineTable(FunctionUnitIndex)
687a34c753fSRafael Auler       .getMCLineSections()
688a34c753fSRafael Auler       .addLineEntry(MCDwarfLineEntry(LineSym, DwarfLoc),
689a34c753fSRafael Auler                     Streamer.getCurrentSectionOnly());
690a34c753fSRafael Auler 
691a34c753fSRafael Auler   return NewLoc;
692a34c753fSRafael Auler }
693a34c753fSRafael Auler 
emitLineInfoEnd(const BinaryFunction & BF,MCSymbol * FunctionEndLabel)694a34c753fSRafael Auler void BinaryEmitter::emitLineInfoEnd(const BinaryFunction &BF,
695a34c753fSRafael Auler                                     MCSymbol *FunctionEndLabel) {
696a34c753fSRafael Auler   DWARFUnit *FunctionCU = BF.getDWARFUnit();
697a34c753fSRafael Auler   assert(FunctionCU && "DWARF unit expected");
698a34c753fSRafael Auler   BC.Ctx->setCurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_END_SEQUENCE, 0, 0);
699a34c753fSRafael Auler   const MCDwarfLoc &DwarfLoc = BC.Ctx->getCurrentDwarfLoc();
700a34c753fSRafael Auler   BC.Ctx->clearDwarfLocSeen();
701a34c753fSRafael Auler   BC.getDwarfLineTable(FunctionCU->getOffset())
702a34c753fSRafael Auler       .getMCLineSections()
703a34c753fSRafael Auler       .addLineEntry(MCDwarfLineEntry(FunctionEndLabel, DwarfLoc),
704a34c753fSRafael Auler                     Streamer.getCurrentSectionOnly());
705a34c753fSRafael Auler }
706a34c753fSRafael Auler 
emitJumpTables(const BinaryFunction & BF)707a34c753fSRafael Auler void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) {
708a34c753fSRafael Auler   MCSection *ReadOnlySection = BC.MOFI->getReadOnlySection();
709a34c753fSRafael Auler   MCSection *ReadOnlyColdSection = BC.MOFI->getContext().getELFSection(
710a34c753fSRafael Auler       ".rodata.cold", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
711a34c753fSRafael Auler 
712a34c753fSRafael Auler   if (!BF.hasJumpTables())
713a34c753fSRafael Auler     return;
714a34c753fSRafael Auler 
7153652483cSRafael Auler   if (opts::PrintJumpTables)
716a34c753fSRafael Auler     outs() << "BOLT-INFO: jump tables for function " << BF << ":\n";
717a34c753fSRafael Auler 
718a34c753fSRafael Auler   for (auto &JTI : BF.jumpTables()) {
719a34c753fSRafael Auler     JumpTable &JT = *JTI.second;
720a34c753fSRafael Auler     if (opts::PrintJumpTables)
721a34c753fSRafael Auler       JT.print(outs());
722a34c753fSRafael Auler     if ((opts::JumpTables == JTS_BASIC || !BF.isSimple()) &&
723a34c753fSRafael Auler         BC.HasRelocations) {
724a34c753fSRafael Auler       JT.updateOriginal();
725a34c753fSRafael Auler     } else {
726a34c753fSRafael Auler       MCSection *HotSection, *ColdSection;
727a34c753fSRafael Auler       if (opts::JumpTables == JTS_BASIC) {
728a34c753fSRafael Auler         // In non-relocation mode we have to emit jump tables in local sections.
729a34c753fSRafael Auler         // This way we only overwrite them when the corresponding function is
730a34c753fSRafael Auler         // overwritten.
731a34c753fSRafael Auler         std::string Name = ".local." + JT.Labels[0]->getName().str();
732a34c753fSRafael Auler         std::replace(Name.begin(), Name.end(), '/', '.');
733a34c753fSRafael Auler         BinarySection &Section =
734a34c753fSRafael Auler             BC.registerOrUpdateSection(Name, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
735a34c753fSRafael Auler         Section.setAnonymous(true);
736a34c753fSRafael Auler         JT.setOutputSection(Section);
737a34c753fSRafael Auler         HotSection = BC.getDataSection(Name);
738a34c753fSRafael Auler         ColdSection = HotSection;
739a34c753fSRafael Auler       } else {
740a34c753fSRafael Auler         if (BF.isSimple()) {
741a34c753fSRafael Auler           HotSection = ReadOnlySection;
742a34c753fSRafael Auler           ColdSection = ReadOnlyColdSection;
743a34c753fSRafael Auler         } else {
744a34c753fSRafael Auler           HotSection = BF.hasProfile() ? ReadOnlySection : ReadOnlyColdSection;
745a34c753fSRafael Auler           ColdSection = HotSection;
746a34c753fSRafael Auler         }
747a34c753fSRafael Auler       }
748a34c753fSRafael Auler       emitJumpTable(JT, HotSection, ColdSection);
749a34c753fSRafael Auler     }
750a34c753fSRafael Auler   }
751a34c753fSRafael Auler }
752a34c753fSRafael Auler 
emitJumpTable(const JumpTable & JT,MCSection * HotSection,MCSection * ColdSection)753a34c753fSRafael Auler void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection,
754a34c753fSRafael Auler                                   MCSection *ColdSection) {
755a34c753fSRafael Auler   // Pre-process entries for aggressive splitting.
756a34c753fSRafael Auler   // Each label represents a separate switch table and gets its own count
757a34c753fSRafael Auler   // determining its destination.
758a34c753fSRafael Auler   std::map<MCSymbol *, uint64_t> LabelCounts;
759a34c753fSRafael Auler   if (opts::JumpTables > JTS_SPLIT && !JT.Counts.empty()) {
760a34c753fSRafael Auler     MCSymbol *CurrentLabel = JT.Labels.at(0);
761a34c753fSRafael Auler     uint64_t CurrentLabelCount = 0;
762a34c753fSRafael Auler     for (unsigned Index = 0; Index < JT.Entries.size(); ++Index) {
763a34c753fSRafael Auler       auto LI = JT.Labels.find(Index * JT.EntrySize);
764a34c753fSRafael Auler       if (LI != JT.Labels.end()) {
765a34c753fSRafael Auler         LabelCounts[CurrentLabel] = CurrentLabelCount;
766a34c753fSRafael Auler         CurrentLabel = LI->second;
767a34c753fSRafael Auler         CurrentLabelCount = 0;
768a34c753fSRafael Auler       }
769a34c753fSRafael Auler       CurrentLabelCount += JT.Counts[Index].Count;
770a34c753fSRafael Auler     }
771a34c753fSRafael Auler     LabelCounts[CurrentLabel] = CurrentLabelCount;
772a34c753fSRafael Auler   } else {
773adf4142fSFangrui Song     Streamer.switchSection(JT.Count > 0 ? HotSection : ColdSection);
774a34c753fSRafael Auler     Streamer.emitValueToAlignment(JT.EntrySize);
775a34c753fSRafael Auler   }
776a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
777a34c753fSRafael Auler   uint64_t Offset = 0;
778a34c753fSRafael Auler   for (MCSymbol *Entry : JT.Entries) {
779a34c753fSRafael Auler     auto LI = JT.Labels.find(Offset);
780a34c753fSRafael Auler     if (LI != JT.Labels.end()) {
781a34c753fSRafael Auler       LLVM_DEBUG(dbgs() << "BOLT-DEBUG: emitting jump table "
782a34c753fSRafael Auler                         << LI->second->getName()
783a34c753fSRafael Auler                         << " (originally was at address 0x"
784a34c753fSRafael Auler                         << Twine::utohexstr(JT.getAddress() + Offset)
785a34c753fSRafael Auler                         << (Offset ? "as part of larger jump table\n" : "\n"));
786a34c753fSRafael Auler       if (!LabelCounts.empty()) {
787a34c753fSRafael Auler         LLVM_DEBUG(dbgs() << "BOLT-DEBUG: jump table count: "
788a34c753fSRafael Auler                           << LabelCounts[LI->second] << '\n');
7893652483cSRafael Auler         if (LabelCounts[LI->second] > 0)
790adf4142fSFangrui Song           Streamer.switchSection(HotSection);
7913652483cSRafael Auler         else
792adf4142fSFangrui Song           Streamer.switchSection(ColdSection);
793a34c753fSRafael Auler         Streamer.emitValueToAlignment(JT.EntrySize);
794a34c753fSRafael Auler       }
795a34c753fSRafael Auler       Streamer.emitLabel(LI->second);
796a34c753fSRafael Auler       LastLabel = LI->second;
797a34c753fSRafael Auler     }
798a34c753fSRafael Auler     if (JT.Type == JumpTable::JTT_NORMAL) {
799a34c753fSRafael Auler       Streamer.emitSymbolValue(Entry, JT.OutputEntrySize);
800a34c753fSRafael Auler     } else { // JTT_PIC
801a34c753fSRafael Auler       const MCSymbolRefExpr *JTExpr =
802a34c753fSRafael Auler           MCSymbolRefExpr::create(LastLabel, Streamer.getContext());
803a34c753fSRafael Auler       const MCSymbolRefExpr *E =
804a34c753fSRafael Auler           MCSymbolRefExpr::create(Entry, Streamer.getContext());
805a34c753fSRafael Auler       const MCBinaryExpr *Value =
806a34c753fSRafael Auler           MCBinaryExpr::createSub(E, JTExpr, Streamer.getContext());
807a34c753fSRafael Auler       Streamer.emitValue(Value, JT.EntrySize);
808a34c753fSRafael Auler     }
809a34c753fSRafael Auler     Offset += JT.EntrySize;
810a34c753fSRafael Auler   }
811a34c753fSRafael Auler }
812a34c753fSRafael Auler 
emitCFIInstruction(const MCCFIInstruction & Inst) const813a34c753fSRafael Auler void BinaryEmitter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
814a34c753fSRafael Auler   switch (Inst.getOperation()) {
815a34c753fSRafael Auler   default:
816a34c753fSRafael Auler     llvm_unreachable("Unexpected instruction");
817a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfaOffset:
818a34c753fSRafael Auler     Streamer.emitCFIDefCfaOffset(Inst.getOffset());
819a34c753fSRafael Auler     break;
820a34c753fSRafael Auler   case MCCFIInstruction::OpAdjustCfaOffset:
821a34c753fSRafael Auler     Streamer.emitCFIAdjustCfaOffset(Inst.getOffset());
822a34c753fSRafael Auler     break;
823a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfa:
824a34c753fSRafael Auler     Streamer.emitCFIDefCfa(Inst.getRegister(), Inst.getOffset());
825a34c753fSRafael Auler     break;
826a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfaRegister:
827a34c753fSRafael Auler     Streamer.emitCFIDefCfaRegister(Inst.getRegister());
828a34c753fSRafael Auler     break;
829a34c753fSRafael Auler   case MCCFIInstruction::OpOffset:
830a34c753fSRafael Auler     Streamer.emitCFIOffset(Inst.getRegister(), Inst.getOffset());
831a34c753fSRafael Auler     break;
832a34c753fSRafael Auler   case MCCFIInstruction::OpRegister:
833a34c753fSRafael Auler     Streamer.emitCFIRegister(Inst.getRegister(), Inst.getRegister2());
834a34c753fSRafael Auler     break;
835a34c753fSRafael Auler   case MCCFIInstruction::OpWindowSave:
836a34c753fSRafael Auler     Streamer.emitCFIWindowSave();
837a34c753fSRafael Auler     break;
838a34c753fSRafael Auler   case MCCFIInstruction::OpNegateRAState:
839a34c753fSRafael Auler     Streamer.emitCFINegateRAState();
840a34c753fSRafael Auler     break;
841a34c753fSRafael Auler   case MCCFIInstruction::OpSameValue:
842a34c753fSRafael Auler     Streamer.emitCFISameValue(Inst.getRegister());
843a34c753fSRafael Auler     break;
844a34c753fSRafael Auler   case MCCFIInstruction::OpGnuArgsSize:
845a34c753fSRafael Auler     Streamer.emitCFIGnuArgsSize(Inst.getOffset());
846a34c753fSRafael Auler     break;
847a34c753fSRafael Auler   case MCCFIInstruction::OpEscape:
848a34c753fSRafael Auler     Streamer.AddComment(Inst.getComment());
849a34c753fSRafael Auler     Streamer.emitCFIEscape(Inst.getValues());
850a34c753fSRafael Auler     break;
851a34c753fSRafael Auler   case MCCFIInstruction::OpRestore:
852a34c753fSRafael Auler     Streamer.emitCFIRestore(Inst.getRegister());
853a34c753fSRafael Auler     break;
854a34c753fSRafael Auler   case MCCFIInstruction::OpUndefined:
855a34c753fSRafael Auler     Streamer.emitCFIUndefined(Inst.getRegister());
856a34c753fSRafael Auler     break;
857a34c753fSRafael Auler   }
858a34c753fSRafael Auler }
859a34c753fSRafael Auler 
860a34c753fSRafael Auler // The code is based on EHStreamer::emitExceptionTable().
emitLSDA(BinaryFunction & BF,bool EmitColdPart)861a34c753fSRafael Auler void BinaryEmitter::emitLSDA(BinaryFunction &BF, bool EmitColdPart) {
862ebe51c4dSMaksim Panchenko   const BinaryFunction::CallSitesType *Sites =
863a34c753fSRafael Auler       EmitColdPart ? &BF.getColdCallSites() : &BF.getCallSites();
864986e5dedSMaksim Panchenko   if (Sites->empty())
865a34c753fSRafael Auler     return;
866a34c753fSRafael Auler 
867a34c753fSRafael Auler   // Calculate callsite table size. Size of each callsite entry is:
868a34c753fSRafael Auler   //
869a34c753fSRafael Auler   //  sizeof(start) + sizeof(length) + sizeof(LP) + sizeof(uleb128(action))
870a34c753fSRafael Auler   //
871a34c753fSRafael Auler   // or
872a34c753fSRafael Auler   //
873a34c753fSRafael Auler   //  sizeof(dwarf::DW_EH_PE_data4) * 3 + sizeof(uleb128(action))
874a34c753fSRafael Auler   uint64_t CallSiteTableLength = Sites->size() * 4 * 3;
875986e5dedSMaksim Panchenko   for (const BinaryFunction::CallSite &CallSite : *Sites)
876a34c753fSRafael Auler     CallSiteTableLength += getULEB128Size(CallSite.Action);
877a34c753fSRafael Auler 
878adf4142fSFangrui Song   Streamer.switchSection(BC.MOFI->getLSDASection());
879a34c753fSRafael Auler 
880a34c753fSRafael Auler   const unsigned TTypeEncoding = BC.TTypeEncoding;
881a34c753fSRafael Auler   const unsigned TTypeEncodingSize = BC.getDWARFEncodingSize(TTypeEncoding);
882a34c753fSRafael Auler   const uint16_t TTypeAlignment = 4;
883a34c753fSRafael Auler 
884a34c753fSRafael Auler   // Type tables have to be aligned at 4 bytes.
885a34c753fSRafael Auler   Streamer.emitValueToAlignment(TTypeAlignment);
886a34c753fSRafael Auler 
887a34c753fSRafael Auler   // Emit the LSDA label.
888a34c753fSRafael Auler   MCSymbol *LSDASymbol =
889a34c753fSRafael Auler       EmitColdPart ? BF.getColdLSDASymbol() : BF.getLSDASymbol();
890a34c753fSRafael Auler   assert(LSDASymbol && "no LSDA symbol set");
891a34c753fSRafael Auler   Streamer.emitLabel(LSDASymbol);
892a34c753fSRafael Auler 
893a34c753fSRafael Auler   // Corresponding FDE start.
89440c2e0faSMaksim Panchenko   const MCSymbol *StartSymbol =
89540c2e0faSMaksim Panchenko       EmitColdPart ? BF.getColdSymbol() : BF.getSymbol();
896a34c753fSRafael Auler 
897a34c753fSRafael Auler   // Emit the LSDA header.
898a34c753fSRafael Auler 
899a34c753fSRafael Auler   // If LPStart is omitted, then the start of the FDE is used as a base for
900a34c753fSRafael Auler   // landing pad displacements. Then if a cold fragment starts with
901a34c753fSRafael Auler   // a landing pad, this means that the first landing pad offset will be 0.
902a34c753fSRafael Auler   // As a result, the exception handling runtime will ignore this landing pad
903a34c753fSRafael Auler   // because zero offset denotes the absence of a landing pad.
904a34c753fSRafael Auler   // For this reason, when the binary has fixed starting address we emit LPStart
905a34c753fSRafael Auler   // as 0 and output the absolute value of the landing pad in the table.
906a34c753fSRafael Auler   //
907a34c753fSRafael Auler   // If the base address can change, we cannot use absolute addresses for
908a34c753fSRafael Auler   // landing pads (at least not without runtime relocations). Hence, we fall
909a34c753fSRafael Auler   // back to emitting landing pads relative to the FDE start.
910a34c753fSRafael Auler   // As we are emitting label differences, we have to guarantee both labels are
911a34c753fSRafael Auler   // defined in the same section and hence cannot place the landing pad into a
912a34c753fSRafael Auler   // cold fragment when the corresponding call site is in the hot fragment.
913a34c753fSRafael Auler   // Because of this issue and the previously described issue of possible
914f263a66bSMaksim Panchenko   // zero-offset landing pad we have to place landing pads in the same section
915f263a66bSMaksim Panchenko   // as the corresponding invokes for shared objects.
916a34c753fSRafael Auler   std::function<void(const MCSymbol *)> emitLandingPad;
917a34c753fSRafael Auler   if (BC.HasFixedLoadAddress) {
918a34c753fSRafael Auler     Streamer.emitIntValue(dwarf::DW_EH_PE_udata4, 1); // LPStart format
919a34c753fSRafael Auler     Streamer.emitIntValue(0, 4);                      // LPStart
920a34c753fSRafael Auler     emitLandingPad = [&](const MCSymbol *LPSymbol) {
921a34c753fSRafael Auler       if (!LPSymbol)
922a34c753fSRafael Auler         Streamer.emitIntValue(0, 4);
923a34c753fSRafael Auler       else
924a34c753fSRafael Auler         Streamer.emitSymbolValue(LPSymbol, 4);
925a34c753fSRafael Auler     };
926a34c753fSRafael Auler   } else {
927a34c753fSRafael Auler     Streamer.emitIntValue(dwarf::DW_EH_PE_omit, 1); // LPStart format
928a34c753fSRafael Auler     emitLandingPad = [&](const MCSymbol *LPSymbol) {
929a34c753fSRafael Auler       if (!LPSymbol)
930a34c753fSRafael Auler         Streamer.emitIntValue(0, 4);
931a34c753fSRafael Auler       else
932a34c753fSRafael Auler         Streamer.emitAbsoluteSymbolDiff(LPSymbol, StartSymbol, 4);
933a34c753fSRafael Auler     };
934a34c753fSRafael Auler   }
935a34c753fSRafael Auler 
936a34c753fSRafael Auler   Streamer.emitIntValue(TTypeEncoding, 1); // TType format
937a34c753fSRafael Auler 
938a34c753fSRafael Auler   // See the comment in EHStreamer::emitExceptionTable() on to use
939a34c753fSRafael Auler   // uleb128 encoding (which can use variable number of bytes to encode the same
940a34c753fSRafael Auler   // value) to ensure type info table is properly aligned at 4 bytes without
941a34c753fSRafael Auler   // iteratively fixing sizes of the tables.
942a34c753fSRafael Auler   unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
943a34c753fSRafael Auler   unsigned TTypeBaseOffset =
944a34c753fSRafael Auler       sizeof(int8_t) +                 // Call site format
945a34c753fSRafael Auler       CallSiteTableLengthSize +        // Call site table length size
946a34c753fSRafael Auler       CallSiteTableLength +            // Call site table length
947a34c753fSRafael Auler       BF.getLSDAActionTable().size() + // Actions table size
948a34c753fSRafael Auler       BF.getLSDATypeTable().size() * TTypeEncodingSize; // Types table size
949a34c753fSRafael Auler   unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
95040c2e0faSMaksim Panchenko   unsigned TotalSize = sizeof(int8_t) +      // LPStart format
951a34c753fSRafael Auler                        sizeof(int8_t) +      // TType format
952a34c753fSRafael Auler                        TTypeBaseOffsetSize + // TType base offset size
953a34c753fSRafael Auler                        TTypeBaseOffset;      // TType base offset
954a34c753fSRafael Auler   unsigned SizeAlign = (4 - TotalSize) & 3;
955a34c753fSRafael Auler 
956a34c753fSRafael Auler   // Account for any extra padding that will be added to the call site table
957a34c753fSRafael Auler   // length.
958a34c753fSRafael Auler   Streamer.emitULEB128IntValue(TTypeBaseOffset,
959a34c753fSRafael Auler                                /*PadTo=*/TTypeBaseOffsetSize + SizeAlign);
960a34c753fSRafael Auler 
961a34c753fSRafael Auler   // Emit the landing pad call site table. We use signed data4 since we can emit
962a34c753fSRafael Auler   // a landing pad in a different part of the split function that could appear
963a34c753fSRafael Auler   // earlier in the address space than LPStart.
964a34c753fSRafael Auler   Streamer.emitIntValue(dwarf::DW_EH_PE_sdata4, 1);
965a34c753fSRafael Auler   Streamer.emitULEB128IntValue(CallSiteTableLength);
966a34c753fSRafael Auler 
967a34c753fSRafael Auler   for (const BinaryFunction::CallSite &CallSite : *Sites) {
968a34c753fSRafael Auler     const MCSymbol *BeginLabel = CallSite.Start;
969a34c753fSRafael Auler     const MCSymbol *EndLabel = CallSite.End;
970a34c753fSRafael Auler 
971a34c753fSRafael Auler     assert(BeginLabel && "start EH label expected");
972a34c753fSRafael Auler     assert(EndLabel && "end EH label expected");
973a34c753fSRafael Auler 
974a34c753fSRafael Auler     // Start of the range is emitted relative to the start of current
975a34c753fSRafael Auler     // function split part.
976a34c753fSRafael Auler     Streamer.emitAbsoluteSymbolDiff(BeginLabel, StartSymbol, 4);
977a34c753fSRafael Auler     Streamer.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4);
978a34c753fSRafael Auler     emitLandingPad(CallSite.LP);
979a34c753fSRafael Auler     Streamer.emitULEB128IntValue(CallSite.Action);
980a34c753fSRafael Auler   }
981a34c753fSRafael Auler 
982a34c753fSRafael Auler   // Write out action, type, and type index tables at the end.
983a34c753fSRafael Auler   //
984a34c753fSRafael Auler   // For action and type index tables there's no need to change the original
985a34c753fSRafael Auler   // table format unless we are doing function splitting, in which case we can
986a34c753fSRafael Auler   // split and optimize the tables.
987a34c753fSRafael Auler   //
988a34c753fSRafael Auler   // For type table we (re-)encode the table using TTypeEncoding matching
989a34c753fSRafael Auler   // the current assembler mode.
9903652483cSRafael Auler   for (uint8_t const &Byte : BF.getLSDAActionTable())
991a34c753fSRafael Auler     Streamer.emitIntValue(Byte, 1);
992a34c753fSRafael Auler 
993a34c753fSRafael Auler   const BinaryFunction::LSDATypeTableTy &TypeTable =
994a34c753fSRafael Auler       (TTypeEncoding & dwarf::DW_EH_PE_indirect) ? BF.getLSDATypeAddressTable()
995a34c753fSRafael Auler                                                  : BF.getLSDATypeTable();
996a34c753fSRafael Auler   assert(TypeTable.size() == BF.getLSDATypeTable().size() &&
997a34c753fSRafael Auler          "indirect type table size mismatch");
998a34c753fSRafael Auler 
999a34c753fSRafael Auler   for (int Index = TypeTable.size() - 1; Index >= 0; --Index) {
1000a34c753fSRafael Auler     const uint64_t TypeAddress = TypeTable[Index];
1001a34c753fSRafael Auler     switch (TTypeEncoding & 0x70) {
1002a34c753fSRafael Auler     default:
1003a34c753fSRafael Auler       llvm_unreachable("unsupported TTypeEncoding");
1004a34c753fSRafael Auler     case dwarf::DW_EH_PE_absptr:
1005a34c753fSRafael Auler       Streamer.emitIntValue(TypeAddress, TTypeEncodingSize);
1006a34c753fSRafael Auler       break;
1007a34c753fSRafael Auler     case dwarf::DW_EH_PE_pcrel: {
1008a34c753fSRafael Auler       if (TypeAddress) {
1009a34c753fSRafael Auler         const MCSymbol *TypeSymbol =
1010a34c753fSRafael Auler             BC.getOrCreateGlobalSymbol(TypeAddress, "TI", 0, TTypeAlignment);
1011a34c753fSRafael Auler         MCSymbol *DotSymbol = BC.Ctx->createNamedTempSymbol();
1012a34c753fSRafael Auler         Streamer.emitLabel(DotSymbol);
1013a34c753fSRafael Auler         const MCBinaryExpr *SubDotExpr = MCBinaryExpr::createSub(
1014a34c753fSRafael Auler             MCSymbolRefExpr::create(TypeSymbol, *BC.Ctx),
1015a34c753fSRafael Auler             MCSymbolRefExpr::create(DotSymbol, *BC.Ctx), *BC.Ctx);
1016a34c753fSRafael Auler         Streamer.emitValue(SubDotExpr, TTypeEncodingSize);
1017a34c753fSRafael Auler       } else {
1018a34c753fSRafael Auler         Streamer.emitIntValue(0, TTypeEncodingSize);
1019a34c753fSRafael Auler       }
1020a34c753fSRafael Auler       break;
1021a34c753fSRafael Auler     }
1022a34c753fSRafael Auler     }
1023a34c753fSRafael Auler   }
10243652483cSRafael Auler   for (uint8_t const &Byte : BF.getLSDATypeIndexTable())
1025a34c753fSRafael Auler     Streamer.emitIntValue(Byte, 1);
1026a34c753fSRafael Auler }
1027a34c753fSRafael Auler 
emitDebugLineInfoForOriginalFunctions()1028a34c753fSRafael Auler void BinaryEmitter::emitDebugLineInfoForOriginalFunctions() {
1029a34c753fSRafael Auler   // If a function is in a CU containing at least one processed function, we
1030a34c753fSRafael Auler   // have to rewrite the whole line table for that CU. For unprocessed functions
1031a34c753fSRafael Auler   // we use data from the input line table.
1032a34c753fSRafael Auler   for (auto &It : BC.getBinaryFunctions()) {
1033a34c753fSRafael Auler     const BinaryFunction &Function = It.second;
1034a34c753fSRafael Auler 
1035a34c753fSRafael Auler     // If the function was emitted, its line info was emitted with it.
1036a34c753fSRafael Auler     if (Function.isEmitted())
1037a34c753fSRafael Auler       continue;
1038a34c753fSRafael Auler 
1039a34c753fSRafael Auler     const DWARFDebugLine::LineTable *LineTable = Function.getDWARFLineTable();
1040a34c753fSRafael Auler     if (!LineTable)
1041a34c753fSRafael Auler       continue; // nothing to update for this function
1042a34c753fSRafael Auler 
1043a34c753fSRafael Auler     const uint64_t Address = Function.getAddress();
1044a34c753fSRafael Auler     std::vector<uint32_t> Results;
1045a34c753fSRafael Auler     if (!LineTable->lookupAddressRange(
1046a34c753fSRafael Auler             {Address, object::SectionedAddress::UndefSection},
1047a34c753fSRafael Auler             Function.getSize(), Results))
1048a34c753fSRafael Auler       continue;
1049a34c753fSRafael Auler 
1050a34c753fSRafael Auler     if (Results.empty())
1051a34c753fSRafael Auler       continue;
1052a34c753fSRafael Auler 
1053a34c753fSRafael Auler     // The first row returned could be the last row matching the start address.
1054a34c753fSRafael Auler     // Find the first row with the same address that is not the end of the
1055a34c753fSRafael Auler     // sequence.
1056a34c753fSRafael Auler     uint64_t FirstRow = Results.front();
1057a34c753fSRafael Auler     while (FirstRow > 0) {
1058a34c753fSRafael Auler       const DWARFDebugLine::Row &PrevRow = LineTable->Rows[FirstRow - 1];
1059a34c753fSRafael Auler       if (PrevRow.Address.Address != Address || PrevRow.EndSequence)
1060a34c753fSRafael Auler         break;
1061a34c753fSRafael Auler       --FirstRow;
1062a34c753fSRafael Auler     }
1063a34c753fSRafael Auler 
1064a34c753fSRafael Auler     const uint64_t EndOfSequenceAddress =
1065a34c753fSRafael Auler         Function.getAddress() + Function.getMaxSize();
1066a34c753fSRafael Auler     BC.getDwarfLineTable(Function.getDWARFUnit()->getOffset())
1067a34c753fSRafael Auler         .addLineTableSequence(LineTable, FirstRow, Results.back(),
1068a34c753fSRafael Auler                               EndOfSequenceAddress);
1069a34c753fSRafael Auler   }
1070a34c753fSRafael Auler 
1071a34c753fSRafael Auler   // For units that are completely unprocessed, use original debug line contents
1072a34c753fSRafael Auler   // eliminating the need to regenerate line info program.
1073a34c753fSRafael Auler   emitDebugLineInfoForUnprocessedCUs();
1074a34c753fSRafael Auler }
1075a34c753fSRafael Auler 
emitDebugLineInfoForUnprocessedCUs()1076a34c753fSRafael Auler void BinaryEmitter::emitDebugLineInfoForUnprocessedCUs() {
1077a34c753fSRafael Auler   // Sorted list of section offsets provides boundaries for section fragments,
1078a34c753fSRafael Auler   // where each fragment is the unit's contribution to debug line section.
1079a34c753fSRafael Auler   std::vector<uint64_t> StmtListOffsets;
1080a34c753fSRafael Auler   StmtListOffsets.reserve(BC.DwCtx->getNumCompileUnits());
1081a34c753fSRafael Auler   for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
1082a34c753fSRafael Auler     DWARFDie CUDie = CU->getUnitDIE();
1083a34c753fSRafael Auler     auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list));
1084a34c753fSRafael Auler     if (!StmtList)
1085a34c753fSRafael Auler       continue;
1086a34c753fSRafael Auler 
1087a34c753fSRafael Auler     StmtListOffsets.push_back(*StmtList);
1088a34c753fSRafael Auler   }
1089d2c87699SAmir Ayupov   llvm::sort(StmtListOffsets);
1090a34c753fSRafael Auler 
1091a34c753fSRafael Auler   // For each CU that was not processed, emit its line info as a binary blob.
1092a34c753fSRafael Auler   for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
1093a34c753fSRafael Auler     if (BC.ProcessedCUs.count(CU.get()))
1094a34c753fSRafael Auler       continue;
1095a34c753fSRafael Auler 
1096a34c753fSRafael Auler     DWARFDie CUDie = CU->getUnitDIE();
1097a34c753fSRafael Auler     auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list));
1098a34c753fSRafael Auler     if (!StmtList)
1099a34c753fSRafael Auler       continue;
1100a34c753fSRafael Auler 
1101a34c753fSRafael Auler     StringRef DebugLineContents = CU->getLineSection().Data;
1102a34c753fSRafael Auler 
1103a34c753fSRafael Auler     const uint64_t Begin = *StmtList;
1104a34c753fSRafael Auler 
1105a34c753fSRafael Auler     // Statement list ends where the next unit contribution begins, or at the
1106a34c753fSRafael Auler     // end of the section.
1107d2c87699SAmir Ayupov     auto It = llvm::upper_bound(StmtListOffsets, Begin);
1108a34c753fSRafael Auler     const uint64_t End =
1109a34c753fSRafael Auler         It == StmtListOffsets.end() ? DebugLineContents.size() : *It;
1110a34c753fSRafael Auler 
1111a34c753fSRafael Auler     BC.getDwarfLineTable(CU->getOffset())
1112a34c753fSRafael Auler         .addRawContents(DebugLineContents.slice(Begin, End));
1113a34c753fSRafael Auler   }
1114a34c753fSRafael Auler }
1115a34c753fSRafael Auler 
emitDataSections(StringRef OrgSecPrefix)1116a34c753fSRafael Auler void BinaryEmitter::emitDataSections(StringRef OrgSecPrefix) {
1117a34c753fSRafael Auler   for (BinarySection &Section : BC.sections()) {
1118a34c753fSRafael Auler     if (!Section.hasRelocations() || !Section.hasSectionRef())
1119a34c753fSRafael Auler       continue;
1120a34c753fSRafael Auler 
1121a34c753fSRafael Auler     StringRef SectionName = Section.getName();
1122a34c753fSRafael Auler     std::string EmitName = Section.isReordered()
1123a34c753fSRafael Auler                                ? std::string(Section.getOutputName())
1124a34c753fSRafael Auler                                : OrgSecPrefix.str() + std::string(SectionName);
1125a34c753fSRafael Auler     Section.emitAsData(Streamer, EmitName);
1126a34c753fSRafael Auler     Section.clearRelocations();
1127a34c753fSRafael Auler   }
1128a34c753fSRafael Auler }
1129a34c753fSRafael Auler 
1130a34c753fSRafael Auler namespace llvm {
1131a34c753fSRafael Auler namespace bolt {
1132a34c753fSRafael Auler 
emitBinaryContext(MCStreamer & Streamer,BinaryContext & BC,StringRef OrgSecPrefix)1133a34c753fSRafael Auler void emitBinaryContext(MCStreamer &Streamer, BinaryContext &BC,
1134a34c753fSRafael Auler                        StringRef OrgSecPrefix) {
1135a34c753fSRafael Auler   BinaryEmitter(Streamer, BC).emitAll(OrgSecPrefix);
1136a34c753fSRafael Auler }
1137a34c753fSRafael Auler 
emitFunctionBody(MCStreamer & Streamer,BinaryFunction & BF,bool EmitColdPart,bool EmitCodeOnly)1138a34c753fSRafael Auler void emitFunctionBody(MCStreamer &Streamer, BinaryFunction &BF,
1139a34c753fSRafael Auler                       bool EmitColdPart, bool EmitCodeOnly) {
114040c2e0faSMaksim Panchenko   BinaryEmitter(Streamer, BF.getBinaryContext())
114140c2e0faSMaksim Panchenko       .emitFunctionBody(BF, EmitColdPart, EmitCodeOnly);
1142a34c753fSRafael Auler }
1143a34c753fSRafael Auler 
1144a34c753fSRafael Auler } // namespace bolt
1145a34c753fSRafael Auler } // namespace llvm
1146