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