xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCAssembler.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/SmallVector.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/iterator.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/MC/MCDwarf.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/SMLoc.h"
22 #include <algorithm>
23 #include <cassert>
24 #include <cstddef>
25 #include <cstdint>
26 #include <memory>
27 #include <string>
28 #include <tuple>
29 #include <utility>
30 #include <vector>
31 
32 namespace llvm {
33 
34 class MCBoundaryAlignFragment;
35 class MCCVDefRangeFragment;
36 class MCCVInlineLineTableFragment;
37 class MCDwarfCallFrameFragment;
38 class MCDwarfLineAddrFragment;
39 class MCEncodedFragment;
40 class MCFixup;
41 class MCLEBFragment;
42 class MCPseudoProbeAddrFragment;
43 class MCRelaxableFragment;
44 class MCSymbolRefExpr;
45 class raw_ostream;
46 class MCAsmBackend;
47 class MCContext;
48 class MCCodeEmitter;
49 class MCFragment;
50 class MCObjectWriter;
51 class MCSection;
52 class MCValue;
53 
54 class MCAssembler {
55 public:
56   friend class MCObjectWriter;
57   using SectionListType = SmallVector<MCSection *, 0>;
58   using const_iterator = pointee_iterator<SectionListType::const_iterator>;
59 
60 private:
61   MCContext &Context;
62 
63   std::unique_ptr<MCAsmBackend> Backend;
64   std::unique_ptr<MCCodeEmitter> Emitter;
65   std::unique_ptr<MCObjectWriter> Writer;
66 
67   bool HasLayout = false;
68   bool HasFinalLayout = false;
69   bool RelaxAll = false;
70 
71   SectionListType Sections;
72 
73   SmallVector<const MCSymbol *, 0> Symbols;
74 
75   mutable SmallVector<std::pair<SMLoc, std::string>, 0> PendingErrors;
76 
77   MCDwarfLineTableParams LTParams;
78 
79   /// The set of function symbols for which a .thumb_func directive has
80   /// been seen.
81   //
82   // FIXME: We really would like this in target specific code rather than
83   // here. Maybe when the relocation stuff moves to target specific,
84   // this can go with it? The streamer would need some target specific
85   // refactoring too.
86   mutable SmallPtrSet<const MCSymbol *, 32> ThumbFuncs;
87 
88   /// The bundle alignment size currently set in the assembler.
89   ///
90   /// By default it's 0, which means bundling is disabled.
91   unsigned BundleAlignSize = 0;
92 
93   /// Evaluate a fixup to a relocatable expression and the value which should be
94   /// placed into the fixup.
95   ///
96   /// \param F The fragment the fixup is inside.
97   /// \param Fixup The fixup to evaluate.
98   /// \param Target [out] On return, the relocatable expression the fixup
99   /// evaluates to.
100   /// \param Value [out] On return, the value of the fixup as currently laid
101   /// out.
102   /// \param RecordReloc Record relocation if needed.
103   /// relocation.
104   bool evaluateFixup(const MCFragment &F, MCFixup &Fixup, MCValue &Target,
105                      uint64_t &Value, bool RecordReloc,
106                      MutableArrayRef<char> Contents) const;
107 
108   /// Check whether a fixup can be satisfied, or whether it needs to be relaxed
109   /// (increased in size, in order to hold its value correctly).
110   bool fixupNeedsRelaxation(const MCRelaxableFragment &, const MCFixup &) const;
111 
112   void layoutSection(MCSection &Sec);
113   /// Perform one layout iteration and return the index of the first stable
114   /// section for subsequent optimization.
115   unsigned relaxOnce(unsigned FirstStable);
116 
117   /// Perform relaxation on a single fragment.
118   bool relaxFragment(MCFragment &F);
119   bool relaxInstruction(MCRelaxableFragment &IF);
120   bool relaxLEB(MCLEBFragment &IF);
121   bool relaxBoundaryAlign(MCBoundaryAlignFragment &BF);
122   bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF);
123   bool relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF);
124   bool relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF);
125   bool relaxCVDefRange(MCCVDefRangeFragment &DF);
126   bool relaxFill(MCFillFragment &F);
127   bool relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &DF);
128 
129 public:
130   /// Construct a new assembler instance.
131   //
132   // FIXME: How are we going to parameterize this? Two obvious options are stay
133   // concrete and require clients to pass in a target like object. The other
134   // option is to make this abstract, and have targets provide concrete
135   // implementations as we do with AsmParser.
136   LLVM_ABI MCAssembler(MCContext &Context,
137                        std::unique_ptr<MCAsmBackend> Backend,
138                        std::unique_ptr<MCCodeEmitter> Emitter,
139                        std::unique_ptr<MCObjectWriter> Writer);
140   MCAssembler(const MCAssembler &) = delete;
141   MCAssembler &operator=(const MCAssembler &) = delete;
142 
143   /// Compute the effective fragment size.
144   LLVM_ABI uint64_t computeFragmentSize(const MCFragment &F) const;
145 
146   LLVM_ABI void layoutBundle(MCFragment *Prev, MCFragment *F) const;
147 
148   // Get the offset of the given fragment inside its containing section.
getFragmentOffset(const MCFragment & F)149   uint64_t getFragmentOffset(const MCFragment &F) const { return F.Offset; }
150 
151   LLVM_ABI uint64_t getSectionAddressSize(const MCSection &Sec) const;
152   LLVM_ABI uint64_t getSectionFileSize(const MCSection &Sec) const;
153 
154   // Get the offset of the given symbol, as computed in the current
155   // layout.
156   // \return True on success.
157   LLVM_ABI bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const;
158 
159   // Variant that reports a fatal error if the offset is not computable.
160   LLVM_ABI uint64_t getSymbolOffset(const MCSymbol &S) const;
161 
162   // If this symbol is equivalent to A + Constant, return A.
163   LLVM_ABI const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const;
164 
165   /// Emit the section contents to \p OS.
166   LLVM_ABI void writeSectionData(raw_ostream &OS,
167                                  const MCSection *Section) const;
168 
169   /// Check whether a given symbol has been flagged with .thumb_func.
170   LLVM_ABI bool isThumbFunc(const MCSymbol *Func) const;
171 
172   /// Flag a function symbol as the target of a .thumb_func directive.
setIsThumbFunc(const MCSymbol * Func)173   void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
174 
175   /// Reuse an assembler instance
176   ///
177   LLVM_ABI void reset();
178 
getContext()179   MCContext &getContext() const { return Context; }
180 
getBackendPtr()181   MCAsmBackend *getBackendPtr() const { return Backend.get(); }
182 
getEmitterPtr()183   MCCodeEmitter *getEmitterPtr() const { return Emitter.get(); }
184 
getBackend()185   MCAsmBackend &getBackend() const { return *Backend; }
186 
getEmitter()187   MCCodeEmitter &getEmitter() const { return *Emitter; }
188 
getWriter()189   MCObjectWriter &getWriter() const { return *Writer; }
190 
getDWARFLinetableParams()191   MCDwarfLineTableParams getDWARFLinetableParams() const { return LTParams; }
192 
193   /// Finish - Do final processing and write the object to the output stream.
194   /// \p Writer is used for custom object writer (as the MCJIT does),
195   /// if not specified it is automatically created from backend.
196   LLVM_ABI void Finish();
197 
198   // Layout all section and prepare them for emission.
199   LLVM_ABI void layout();
200 
hasLayout()201   bool hasLayout() const { return HasLayout; }
hasFinalLayout()202   bool hasFinalLayout() const { return HasFinalLayout; }
getRelaxAll()203   bool getRelaxAll() const { return RelaxAll; }
setRelaxAll(bool Value)204   void setRelaxAll(bool Value) { RelaxAll = Value; }
205 
isBundlingEnabled()206   bool isBundlingEnabled() const { return BundleAlignSize != 0; }
207 
getBundleAlignSize()208   unsigned getBundleAlignSize() const { return BundleAlignSize; }
209 
setBundleAlignSize(unsigned Size)210   void setBundleAlignSize(unsigned Size) {
211     assert((Size == 0 || !(Size & (Size - 1))) &&
212            "Expect a power-of-two bundle align size");
213     BundleAlignSize = Size;
214   }
215 
begin()216   const_iterator begin() const { return Sections.begin(); }
end()217   const_iterator end() const { return Sections.end(); }
218 
getSymbols()219   SmallVectorImpl<const MCSymbol *> &getSymbols() { return Symbols; }
220   iterator_range<pointee_iterator<
221       typename SmallVector<const MCSymbol *, 0>::const_iterator>>
symbols()222   symbols() const {
223     return make_pointee_range(Symbols);
224   }
225 
226   LLVM_ABI bool registerSection(MCSection &Section);
227   LLVM_ABI bool registerSymbol(const MCSymbol &Symbol);
228 
229   /// Write the necessary bundle padding to \p OS.
230   /// Expects a fragment \p F containing instructions and its size \p FSize.
231   LLVM_ABI void writeFragmentPadding(raw_ostream &OS,
232                                      const MCEncodedFragment &F,
233                                      uint64_t FSize) const;
234 
235   LLVM_ABI void reportError(SMLoc L, const Twine &Msg) const;
236   // Record pending errors during layout iteration, as they may go away once the
237   // layout is finalized.
238   LLVM_ABI void recordError(SMLoc L, const Twine &Msg) const;
239   LLVM_ABI void flushPendingErrors() const;
240 
241   LLVM_ABI void dump() const;
242 };
243 
244 } // end namespace llvm
245 
246 #endif // LLVM_MC_MCASSEMBLER_H
247