Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:12

0001 //===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_MC_MCASSEMBLER_H
0010 #define LLVM_MC_MCASSEMBLER_H
0011 
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/SmallPtrSet.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include "llvm/ADT/iterator.h"
0017 #include "llvm/ADT/iterator_range.h"
0018 #include "llvm/MC/MCDwarf.h"
0019 #include "llvm/MC/MCSymbol.h"
0020 #include "llvm/Support/SMLoc.h"
0021 #include <algorithm>
0022 #include <cassert>
0023 #include <cstddef>
0024 #include <cstdint>
0025 #include <memory>
0026 #include <string>
0027 #include <tuple>
0028 #include <utility>
0029 #include <vector>
0030 
0031 namespace llvm {
0032 
0033 class MCBoundaryAlignFragment;
0034 class MCCVDefRangeFragment;
0035 class MCCVInlineLineTableFragment;
0036 class MCDwarfCallFrameFragment;
0037 class MCDwarfLineAddrFragment;
0038 class MCEncodedFragment;
0039 class MCFixup;
0040 class MCLEBFragment;
0041 class MCPseudoProbeAddrFragment;
0042 class MCRelaxableFragment;
0043 class MCSymbolRefExpr;
0044 class raw_ostream;
0045 class MCAsmBackend;
0046 class MCContext;
0047 class MCCodeEmitter;
0048 class MCFragment;
0049 class MCObjectWriter;
0050 class MCSection;
0051 class MCValue;
0052 
0053 class MCAssembler {
0054 public:
0055   friend class MCObjectWriter;
0056   using SectionListType = SmallVector<MCSection *, 0>;
0057   using const_iterator = pointee_iterator<SectionListType::const_iterator>;
0058 
0059 private:
0060   MCContext &Context;
0061 
0062   std::unique_ptr<MCAsmBackend> Backend;
0063   std::unique_ptr<MCCodeEmitter> Emitter;
0064   std::unique_ptr<MCObjectWriter> Writer;
0065 
0066   bool HasLayout = false;
0067   bool RelaxAll = false;
0068 
0069   SectionListType Sections;
0070 
0071   SmallVector<const MCSymbol *, 0> Symbols;
0072 
0073   MCDwarfLineTableParams LTParams;
0074 
0075   /// The set of function symbols for which a .thumb_func directive has
0076   /// been seen.
0077   //
0078   // FIXME: We really would like this in target specific code rather than
0079   // here. Maybe when the relocation stuff moves to target specific,
0080   // this can go with it? The streamer would need some target specific
0081   // refactoring too.
0082   mutable SmallPtrSet<const MCSymbol *, 32> ThumbFuncs;
0083 
0084   /// The bundle alignment size currently set in the assembler.
0085   ///
0086   /// By default it's 0, which means bundling is disabled.
0087   unsigned BundleAlignSize = 0;
0088 
0089   /// Evaluate a fixup to a relocatable expression and the value which should be
0090   /// placed into the fixup.
0091   ///
0092   /// \param Fixup The fixup to evaluate.
0093   /// \param DF The fragment the fixup is inside.
0094   /// \param Target [out] On return, the relocatable expression the fixup
0095   /// evaluates to.
0096   /// \param Value [out] On return, the value of the fixup as currently laid
0097   /// out.
0098   /// \param WasForced [out] On return, the value in the fixup is set to the
0099   /// correct value if WasForced is true, even if evaluateFixup returns false.
0100   /// \return Whether the fixup value was fully resolved. This is true if the
0101   /// \p Value result is fixed, otherwise the value may change due to
0102   /// relocation.
0103   bool evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
0104                      MCValue &Target, const MCSubtargetInfo *STI,
0105                      uint64_t &Value, bool &WasForced) const;
0106 
0107   /// Check whether a fixup can be satisfied, or whether it needs to be relaxed
0108   /// (increased in size, in order to hold its value correctly).
0109   bool fixupNeedsRelaxation(const MCFixup &Fixup, const MCRelaxableFragment *DF) const;
0110 
0111   /// Check whether the given fragment needs relaxation.
0112   bool fragmentNeedsRelaxation(const MCRelaxableFragment *IF) const;
0113 
0114   /// Perform one layout iteration and return true if any offsets
0115   /// were adjusted.
0116   bool layoutOnce();
0117 
0118   /// Perform relaxation on a single fragment - returns true if the fragment
0119   /// changes as a result of relaxation.
0120   bool relaxFragment(MCFragment &F);
0121   bool relaxInstruction(MCRelaxableFragment &IF);
0122   bool relaxLEB(MCLEBFragment &IF);
0123   bool relaxBoundaryAlign(MCBoundaryAlignFragment &BF);
0124   bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF);
0125   bool relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF);
0126   bool relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF);
0127   bool relaxCVDefRange(MCCVDefRangeFragment &DF);
0128   bool relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &DF);
0129 
0130   std::tuple<MCValue, uint64_t, bool>
0131   handleFixup(MCFragment &F, const MCFixup &Fixup, const MCSubtargetInfo *STI);
0132 
0133 public:
0134   /// Construct a new assembler instance.
0135   //
0136   // FIXME: How are we going to parameterize this? Two obvious options are stay
0137   // concrete and require clients to pass in a target like object. The other
0138   // option is to make this abstract, and have targets provide concrete
0139   // implementations as we do with AsmParser.
0140   MCAssembler(MCContext &Context, std::unique_ptr<MCAsmBackend> Backend,
0141               std::unique_ptr<MCCodeEmitter> Emitter,
0142               std::unique_ptr<MCObjectWriter> Writer);
0143   MCAssembler(const MCAssembler &) = delete;
0144   MCAssembler &operator=(const MCAssembler &) = delete;
0145 
0146   /// Compute the effective fragment size.
0147   uint64_t computeFragmentSize(const MCFragment &F) const;
0148 
0149   void layoutBundle(MCFragment *Prev, MCFragment *F) const;
0150   void ensureValid(MCSection &Sec) const;
0151 
0152   // Get the offset of the given fragment inside its containing section.
0153   uint64_t getFragmentOffset(const MCFragment &F) const;
0154 
0155   uint64_t getSectionAddressSize(const MCSection &Sec) const;
0156   uint64_t getSectionFileSize(const MCSection &Sec) const;
0157 
0158   // Get the offset of the given symbol, as computed in the current
0159   // layout.
0160   // \return True on success.
0161   bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const;
0162 
0163   // Variant that reports a fatal error if the offset is not computable.
0164   uint64_t getSymbolOffset(const MCSymbol &S) const;
0165 
0166   // If this symbol is equivalent to A + Constant, return A.
0167   const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const;
0168 
0169   /// Emit the section contents to \p OS.
0170   void writeSectionData(raw_ostream &OS, const MCSection *Section) const;
0171 
0172   /// Check whether a given symbol has been flagged with .thumb_func.
0173   bool isThumbFunc(const MCSymbol *Func) const;
0174 
0175   /// Flag a function symbol as the target of a .thumb_func directive.
0176   void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
0177 
0178   /// Reuse an assembler instance
0179   ///
0180   void reset();
0181 
0182   MCContext &getContext() const { return Context; }
0183 
0184   MCAsmBackend *getBackendPtr() const { return Backend.get(); }
0185 
0186   MCCodeEmitter *getEmitterPtr() const { return Emitter.get(); }
0187 
0188   MCAsmBackend &getBackend() const { return *Backend; }
0189 
0190   MCCodeEmitter &getEmitter() const { return *Emitter; }
0191 
0192   MCObjectWriter &getWriter() const { return *Writer; }
0193 
0194   MCDwarfLineTableParams getDWARFLinetableParams() const { return LTParams; }
0195 
0196   /// Finish - Do final processing and write the object to the output stream.
0197   /// \p Writer is used for custom object writer (as the MCJIT does),
0198   /// if not specified it is automatically created from backend.
0199   void Finish();
0200 
0201   // Layout all section and prepare them for emission.
0202   void layout();
0203 
0204   bool hasLayout() const { return HasLayout; }
0205   bool getRelaxAll() const { return RelaxAll; }
0206   void setRelaxAll(bool Value) { RelaxAll = Value; }
0207 
0208   bool isBundlingEnabled() const { return BundleAlignSize != 0; }
0209 
0210   unsigned getBundleAlignSize() const { return BundleAlignSize; }
0211 
0212   void setBundleAlignSize(unsigned Size) {
0213     assert((Size == 0 || !(Size & (Size - 1))) &&
0214            "Expect a power-of-two bundle align size");
0215     BundleAlignSize = Size;
0216   }
0217 
0218   const_iterator begin() const { return Sections.begin(); }
0219   const_iterator end() const { return Sections.end(); }
0220 
0221   SmallVectorImpl<const MCSymbol *> &getSymbols() { return Symbols; }
0222   iterator_range<pointee_iterator<
0223       typename SmallVector<const MCSymbol *, 0>::const_iterator>>
0224   symbols() const {
0225     return make_pointee_range(Symbols);
0226   }
0227 
0228   bool registerSection(MCSection &Section);
0229   bool registerSymbol(const MCSymbol &Symbol);
0230 
0231   /// Write the necessary bundle padding to \p OS.
0232   /// Expects a fragment \p F containing instructions and its size \p FSize.
0233   void writeFragmentPadding(raw_ostream &OS, const MCEncodedFragment &F,
0234                             uint64_t FSize) const;
0235 
0236   void dump() const;
0237 };
0238 
0239 } // end namespace llvm
0240 
0241 #endif // LLVM_MC_MCASSEMBLER_H