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