1//===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_MC_MCASSEMBLER_H
10#define LLVM_MC_MCASSEMBLER_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/SmallPtrSet.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/iterator.h"
16#include "llvm/ADT/iterator_range.h"
17#include "llvm/BinaryFormat/MachO.h"
18#include "llvm/MC/MCDirectives.h"
19#include "llvm/MC/MCDwarf.h"
20#include "llvm/MC/MCLinkerOptimizationHint.h"
21#include "llvm/MC/MCSymbol.h"
22#include "llvm/Support/SMLoc.h"
23#include "llvm/Support/VersionTuple.h"
24#include <algorithm>
25#include <cassert>
26#include <cstddef>
27#include <cstdint>
28#include <memory>
29#include <string>
30#include <tuple>
31#include <utility>
32#include <vector>
33
34namespace llvm {
35
36class MCBoundaryAlignFragment;
37class MCCVDefRangeFragment;
38class MCCVInlineLineTableFragment;
39class MCDwarfCallFrameFragment;
40class MCDwarfLineAddrFragment;
41class MCEncodedFragment;
42class MCFixup;
43class MCLEBFragment;
44class MCPseudoProbeAddrFragment;
45class MCRelaxableFragment;
46class MCSymbolRefExpr;
47class raw_ostream;
48class MCAsmBackend;
49class MCAsmLayout;
50class MCContext;
51class MCCodeEmitter;
52class MCFragment;
53class MCObjectWriter;
54class MCSection;
55class MCValue;
56
57// FIXME: This really doesn't belong here. See comments below.
58struct IndirectSymbolData {
59 MCSymbol *Symbol;
60 MCSection *Section;
61};
62
63// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk
64// to one another.
65struct DataRegionData {
66 // This enum should be kept in sync w/ the mach-o definition in
67 // llvm/Object/MachOFormat.h.
68 enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind;
69 MCSymbol *Start;
70 MCSymbol *End;
71};
72
73class MCAssembler {
74 friend class MCAsmLayout;
75
76public:
77 using SectionListType = std::vector<MCSection *>;
78 using SymbolDataListType = std::vector<const MCSymbol *>;
79
80 using const_iterator = pointee_iterator<SectionListType::const_iterator>;
81 using iterator = pointee_iterator<SectionListType::iterator>;
82
83 using const_symbol_iterator =
84 pointee_iterator<SymbolDataListType::const_iterator>;
85 using symbol_iterator = pointee_iterator<SymbolDataListType::iterator>;
86
87 using symbol_range = iterator_range<symbol_iterator>;
88 using const_symbol_range = iterator_range<const_symbol_iterator>;
89
90 using const_indirect_symbol_iterator =
91 std::vector<IndirectSymbolData>::const_iterator;
92 using indirect_symbol_iterator = std::vector<IndirectSymbolData>::iterator;
93
94 using const_data_region_iterator =
95 std::vector<DataRegionData>::const_iterator;
96 using data_region_iterator = std::vector<DataRegionData>::iterator;
97
98 /// MachO specific deployment target version info.
99 // A Major version of 0 indicates that no version information was supplied
100 // and so the corresponding load command should not be emitted.
101 using VersionInfoType = struct {
102 bool EmitBuildVersion;
103 union {
104 MCVersionMinType Type; ///< Used when EmitBuildVersion==false.
105 MachO::PlatformType Platform; ///< Used when EmitBuildVersion==true.
106 } TypeOrPlatform;
107 unsigned Major;
108 unsigned Minor;
109 unsigned Update;
110 /// An optional version of the SDK that was used to build the source.
111 VersionTuple SDKVersion;
112 };
113
114private:
115 MCContext &Context;
116
117 std::unique_ptr<MCAsmBackend> Backend;
118
119 std::unique_ptr<MCCodeEmitter> Emitter;
120
121 std::unique_ptr<MCObjectWriter> Writer;
122
123 SectionListType Sections;
124
125 SymbolDataListType Symbols;
126
127 std::vector<IndirectSymbolData> IndirectSymbols;
128
129 std::vector<DataRegionData> DataRegions;
130
131 /// The list of linker options to propagate into the object file.
132 std::vector<std::vector<std::string>> LinkerOptions;
133
134 /// List of declared file names
135 std::vector<std::pair<std::string, size_t>> FileNames;
136 // Optional compiler version.
137 std::string CompilerVersion;
138
139 MCDwarfLineTableParams LTParams;
140
141 /// The set of function symbols for which a .thumb_func directive has
142 /// been seen.
143 //
144 // FIXME: We really would like this in target specific code rather than
145 // here. Maybe when the relocation stuff moves to target specific,
146 // this can go with it? The streamer would need some target specific
147 // refactoring too.
148 mutable SmallPtrSet<const MCSymbol *, 32> ThumbFuncs;
149
150 /// The bundle alignment size currently set in the assembler.
151 ///
152 /// By default it's 0, which means bundling is disabled.
153 unsigned BundleAlignSize;
154
155 bool RelaxAll : 1;
156 bool SubsectionsViaSymbols : 1;
157 bool IncrementalLinkerCompatible : 1;
158
159 /// ELF specific e_header flags
160 // It would be good if there were an MCELFAssembler class to hold this.
161 // ELF header flags are used both by the integrated and standalone assemblers.
162 // Access to the flags is necessary in cases where assembler directives affect
163 // which flags to be set.
164 unsigned ELFHeaderEFlags;
165
166 /// Used to communicate Linker Optimization Hint information between
167 /// the Streamer and the .o writer
168 MCLOHContainer LOHContainer;
169
170 VersionInfoType VersionInfo;
171 VersionInfoType DarwinTargetVariantVersionInfo;
172
173 /// Evaluate a fixup to a relocatable expression and the value which should be
174 /// placed into the fixup.
175 ///
176 /// \param Layout The layout to use for evaluation.
177 /// \param Fixup The fixup to evaluate.
178 /// \param DF The fragment the fixup is inside.
179 /// \param Target [out] On return, the relocatable expression the fixup
180 /// evaluates to.
181 /// \param Value [out] On return, the value of the fixup as currently laid
182 /// out.
183 /// \param WasForced [out] On return, the value in the fixup is set to the
184 /// correct value if WasForced is true, even if evaluateFixup returns false.
185 /// \return Whether the fixup value was fully resolved. This is true if the
186 /// \p Value result is fixed, otherwise the value may change due to
187 /// relocation.
188 bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup,
189 const MCFragment *DF, MCValue &Target,
190 const MCSubtargetInfo *STI, uint64_t &Value,
191 bool &WasForced) const;
192
193 /// Check whether a fixup can be satisfied, or whether it needs to be relaxed
194 /// (increased in size, in order to hold its value correctly).
195 bool fixupNeedsRelaxation(const MCFixup &Fixup, const MCRelaxableFragment *DF,
196 const MCAsmLayout &Layout) const;
197
198 /// Check whether the given fragment needs relaxation.
199 bool fragmentNeedsRelaxation(const MCRelaxableFragment *IF,
200 const MCAsmLayout &Layout) const;
201
202 /// Perform one layout iteration and return true if any offsets
203 /// were adjusted.
204 bool layoutOnce(MCAsmLayout &Layout);
205
206 /// Perform one layout iteration of the given section and return true
207 /// if any offsets were adjusted.
208 bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec);
209
210 /// Perform relaxation on a single fragment - returns true if the fragment
211 /// changes as a result of relaxation.
212 bool relaxFragment(MCAsmLayout &Layout, MCFragment &F);
213 bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF);
214 bool relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF);
215 bool relaxBoundaryAlign(MCAsmLayout &Layout, MCBoundaryAlignFragment &BF);
216 bool relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF);
217 bool relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
218 MCDwarfCallFrameFragment &DF);
219 bool relaxCVInlineLineTable(MCAsmLayout &Layout,
220 MCCVInlineLineTableFragment &DF);
221 bool relaxCVDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &DF);
222 bool relaxPseudoProbeAddr(MCAsmLayout &Layout, MCPseudoProbeAddrFragment &DF);
223
224 /// finishLayout - Finalize a layout, including fragment lowering.
225 void finishLayout(MCAsmLayout &Layout);
226
227 std::tuple<MCValue, uint64_t, bool> handleFixup(const MCAsmLayout &Layout,
228 MCFragment &F,
229 const MCFixup &Fixup,
230 const MCSubtargetInfo *STI);
231
232public:
233 struct Symver {
234 SMLoc Loc;
235 const MCSymbol *Sym;
236 StringRef Name;
237 // True if .symver *, *@@@* or .symver *, *, remove.
238 bool KeepOriginalSym;
239 };
240 std::vector<Symver> Symvers;
241
242 /// Construct a new assembler instance.
243 //
244 // FIXME: How are we going to parameterize this? Two obvious options are stay
245 // concrete and require clients to pass in a target like object. The other
246 // option is to make this abstract, and have targets provide concrete
247 // implementations as we do with AsmParser.
248 MCAssembler(MCContext &Context, std::unique_ptr<MCAsmBackend> Backend,
249 std::unique_ptr<MCCodeEmitter> Emitter,
250 std::unique_ptr<MCObjectWriter> Writer);
251 MCAssembler(const MCAssembler &) = delete;
252 MCAssembler &operator=(const MCAssembler &) = delete;
253 ~MCAssembler();
254
255 /// Compute the effective fragment size assuming it is laid out at the given
256 /// \p SectionAddress and \p FragmentOffset.
257 uint64_t computeFragmentSize(const MCAsmLayout &Layout,
258 const MCFragment &F) const;
259
260 /// Find the symbol which defines the atom containing the given symbol, or
261 /// null if there is no such symbol.
262 const MCSymbol *getAtom(const MCSymbol &S) const;
263
264 /// Check whether a particular symbol is visible to the linker and is required
265 /// in the symbol table, or whether it can be discarded by the assembler. This
266 /// also effects whether the assembler treats the label as potentially
267 /// defining a separate atom.
268 bool isSymbolLinkerVisible(const MCSymbol &SD) const;
269
270 /// Emit the section contents to \p OS.
271 void writeSectionData(raw_ostream &OS, const MCSection *Section,
272 const MCAsmLayout &Layout) const;
273
274 /// Check whether a given symbol has been flagged with .thumb_func.
275 bool isThumbFunc(const MCSymbol *Func) const;
276
277 /// Flag a function symbol as the target of a .thumb_func directive.
278 void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Ptr: Func); }
279
280 /// ELF e_header flags
281 unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; }
282 void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; }
283
284 /// MachO deployment target version information.
285 const VersionInfoType &getVersionInfo() const { return VersionInfo; }
286 void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor,
287 unsigned Update,
288 VersionTuple SDKVersion = VersionTuple()) {
289 VersionInfo.EmitBuildVersion = false;
290 VersionInfo.TypeOrPlatform.Type = Type;
291 VersionInfo.Major = Major;
292 VersionInfo.Minor = Minor;
293 VersionInfo.Update = Update;
294 VersionInfo.SDKVersion = SDKVersion;
295 }
296 void setBuildVersion(MachO::PlatformType Platform, unsigned Major,
297 unsigned Minor, unsigned Update,
298 VersionTuple SDKVersion = VersionTuple()) {
299 VersionInfo.EmitBuildVersion = true;
300 VersionInfo.TypeOrPlatform.Platform = Platform;
301 VersionInfo.Major = Major;
302 VersionInfo.Minor = Minor;
303 VersionInfo.Update = Update;
304 VersionInfo.SDKVersion = SDKVersion;
305 }
306
307 const VersionInfoType &getDarwinTargetVariantVersionInfo() const {
308 return DarwinTargetVariantVersionInfo;
309 }
310 void setDarwinTargetVariantBuildVersion(MachO::PlatformType Platform,
311 unsigned Major, unsigned Minor,
312 unsigned Update,
313 VersionTuple SDKVersion) {
314 DarwinTargetVariantVersionInfo.EmitBuildVersion = true;
315 DarwinTargetVariantVersionInfo.TypeOrPlatform.Platform = Platform;
316 DarwinTargetVariantVersionInfo.Major = Major;
317 DarwinTargetVariantVersionInfo.Minor = Minor;
318 DarwinTargetVariantVersionInfo.Update = Update;
319 DarwinTargetVariantVersionInfo.SDKVersion = SDKVersion;
320 }
321
322 /// Reuse an assembler instance
323 ///
324 void reset();
325
326 MCContext &getContext() const { return Context; }
327
328 MCAsmBackend *getBackendPtr() const { return Backend.get(); }
329
330 MCCodeEmitter *getEmitterPtr() const { return Emitter.get(); }
331
332 MCObjectWriter *getWriterPtr() const { return Writer.get(); }
333
334 MCAsmBackend &getBackend() const { return *Backend; }
335
336 MCCodeEmitter &getEmitter() const { return *Emitter; }
337
338 MCObjectWriter &getWriter() const { return *Writer; }
339
340 MCDwarfLineTableParams getDWARFLinetableParams() const { return LTParams; }
341 void setDWARFLinetableParams(MCDwarfLineTableParams P) { LTParams = P; }
342
343 /// Finish - Do final processing and write the object to the output stream.
344 /// \p Writer is used for custom object writer (as the MCJIT does),
345 /// if not specified it is automatically created from backend.
346 void Finish();
347
348 // Layout all section and prepare them for emission.
349 void layout(MCAsmLayout &Layout);
350
351 // FIXME: This does not belong here.
352 bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; }
353 void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; }
354
355 bool isIncrementalLinkerCompatible() const {
356 return IncrementalLinkerCompatible;
357 }
358 void setIncrementalLinkerCompatible(bool Value) {
359 IncrementalLinkerCompatible = Value;
360 }
361
362 bool getRelaxAll() const { return RelaxAll; }
363 void setRelaxAll(bool Value) { RelaxAll = Value; }
364
365 bool isBundlingEnabled() const { return BundleAlignSize != 0; }
366
367 unsigned getBundleAlignSize() const { return BundleAlignSize; }
368
369 void setBundleAlignSize(unsigned Size) {
370 assert((Size == 0 || !(Size & (Size - 1))) &&
371 "Expect a power-of-two bundle align size");
372 BundleAlignSize = Size;
373 }
374
375 /// \name Section List Access
376 /// @{
377
378 iterator begin() { return Sections.begin(); }
379 const_iterator begin() const { return Sections.begin(); }
380
381 iterator end() { return Sections.end(); }
382 const_iterator end() const { return Sections.end(); }
383
384 size_t size() const { return Sections.size(); }
385
386 /// @}
387 /// \name Symbol List Access
388 /// @{
389 symbol_iterator symbol_begin() { return Symbols.begin(); }
390 const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
391
392 symbol_iterator symbol_end() { return Symbols.end(); }
393 const_symbol_iterator symbol_end() const { return Symbols.end(); }
394
395 symbol_range symbols() { return make_range(x: symbol_begin(), y: symbol_end()); }
396 const_symbol_range symbols() const {
397 return make_range(x: symbol_begin(), y: symbol_end());
398 }
399
400 size_t symbol_size() const { return Symbols.size(); }
401
402 /// @}
403 /// \name Indirect Symbol List Access
404 /// @{
405
406 // FIXME: This is a total hack, this should not be here. Once things are
407 // factored so that the streamer has direct access to the .o writer, it can
408 // disappear.
409 std::vector<IndirectSymbolData> &getIndirectSymbols() {
410 return IndirectSymbols;
411 }
412
413 indirect_symbol_iterator indirect_symbol_begin() {
414 return IndirectSymbols.begin();
415 }
416 const_indirect_symbol_iterator indirect_symbol_begin() const {
417 return IndirectSymbols.begin();
418 }
419
420 indirect_symbol_iterator indirect_symbol_end() {
421 return IndirectSymbols.end();
422 }
423 const_indirect_symbol_iterator indirect_symbol_end() const {
424 return IndirectSymbols.end();
425 }
426
427 size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
428
429 /// @}
430 /// \name Linker Option List Access
431 /// @{
432
433 std::vector<std::vector<std::string>> &getLinkerOptions() {
434 return LinkerOptions;
435 }
436
437 /// @}
438 /// \name Data Region List Access
439 /// @{
440
441 // FIXME: This is a total hack, this should not be here. Once things are
442 // factored so that the streamer has direct access to the .o writer, it can
443 // disappear.
444 std::vector<DataRegionData> &getDataRegions() { return DataRegions; }
445
446 data_region_iterator data_region_begin() { return DataRegions.begin(); }
447 const_data_region_iterator data_region_begin() const {
448 return DataRegions.begin();
449 }
450
451 data_region_iterator data_region_end() { return DataRegions.end(); }
452 const_data_region_iterator data_region_end() const {
453 return DataRegions.end();
454 }
455
456 size_t data_region_size() const { return DataRegions.size(); }
457
458 /// @}
459 /// \name Data Region List Access
460 /// @{
461
462 // FIXME: This is a total hack, this should not be here. Once things are
463 // factored so that the streamer has direct access to the .o writer, it can
464 // disappear.
465 MCLOHContainer &getLOHContainer() { return LOHContainer; }
466 const MCLOHContainer &getLOHContainer() const {
467 return const_cast<MCAssembler *>(this)->getLOHContainer();
468 }
469
470 struct CGProfileEntry {
471 const MCSymbolRefExpr *From;
472 const MCSymbolRefExpr *To;
473 uint64_t Count;
474 };
475 std::vector<CGProfileEntry> CGProfile;
476 /// @}
477 /// \name Backend Data Access
478 /// @{
479
480 bool registerSection(MCSection &Section);
481 bool registerSymbol(const MCSymbol &Symbol);
482
483 MutableArrayRef<std::pair<std::string, size_t>> getFileNames() {
484 return FileNames;
485 }
486
487 void addFileName(StringRef FileName) {
488 FileNames.emplace_back(args: std::string(FileName), args: Symbols.size());
489 }
490
491 void setCompilerVersion(std::string CompilerVers) {
492 if (CompilerVersion.empty())
493 CompilerVersion = std::move(CompilerVers);
494 }
495 StringRef getCompilerVersion() { return CompilerVersion; }
496
497 /// Write the necessary bundle padding to \p OS.
498 /// Expects a fragment \p F containing instructions and its size \p FSize.
499 void writeFragmentPadding(raw_ostream &OS, const MCEncodedFragment &F,
500 uint64_t FSize) const;
501
502 /// @}
503
504 void dump() const;
505};
506
507/// Compute the amount of padding required before the fragment \p F to
508/// obey bundling restrictions, where \p FOffset is the fragment's offset in
509/// its section and \p FSize is the fragment's size.
510uint64_t computeBundlePadding(const MCAssembler &Assembler,
511 const MCEncodedFragment *F, uint64_t FOffset,
512 uint64_t FSize);
513
514} // end namespace llvm
515
516#endif // LLVM_MC_MCASSEMBLER_H
517

source code of llvm/include/llvm/MC/MCAssembler.h