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