Home | History | Annotate | Line # | Download | only in MC
      1 //===- MCObjectStreamer.h - MCStreamer Object File Interface ----*- 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_MCOBJECTSTREAMER_H
     10 #define LLVM_MC_MCOBJECTSTREAMER_H
     11 
     12 #include "llvm/ADT/SetVector.h"
     13 #include "llvm/ADT/SmallVector.h"
     14 #include "llvm/MC/MCAssembler.h"
     15 #include "llvm/MC/MCSection.h"
     16 #include "llvm/MC/MCStreamer.h"
     17 
     18 namespace llvm {
     19 class MCAssembler;
     20 class MCCodeEmitter;
     21 class MCSubtargetInfo;
     22 class MCExpr;
     23 class MCFragment;
     24 class MCDataFragment;
     25 class MCAsmBackend;
     26 class raw_ostream;
     27 class raw_pwrite_stream;
     28 
     29 /// Streaming object file generation interface.
     30 ///
     31 /// This class provides an implementation of the MCStreamer interface which is
     32 /// suitable for use with the assembler backend. Specific object file formats
     33 /// are expected to subclass this interface to implement directives specific
     34 /// to that file format or custom semantics expected by the object writer
     35 /// implementation.
     36 class MCObjectStreamer : public MCStreamer {
     37   std::unique_ptr<MCAssembler> Assembler;
     38   MCSection::iterator CurInsertionPoint;
     39   bool EmitEHFrame;
     40   bool EmitDebugFrame;
     41   SmallVector<MCSymbol *, 2> PendingLabels;
     42   SmallSetVector<MCSection *, 4> PendingLabelSections;
     43   unsigned CurSubsectionIdx;
     44   struct PendingMCFixup {
     45     const MCSymbol *Sym;
     46     MCFixup Fixup;
     47     MCDataFragment *DF;
     48     PendingMCFixup(const MCSymbol *McSym, MCDataFragment *F, MCFixup McFixup)
     49         : Sym(McSym), Fixup(McFixup), DF(F) {}
     50   };
     51   SmallVector<PendingMCFixup, 2> PendingFixups;
     52 
     53   virtual void emitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
     54   void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
     55   void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
     56   MCSymbol *emitCFILabel() override;
     57   void emitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI);
     58   void resolvePendingFixups();
     59 
     60 protected:
     61   MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
     62                    std::unique_ptr<MCObjectWriter> OW,
     63                    std::unique_ptr<MCCodeEmitter> Emitter);
     64   ~MCObjectStreamer();
     65 
     66 public:
     67   /// state management
     68   void reset() override;
     69 
     70   /// Object streamers require the integrated assembler.
     71   bool isIntegratedAssemblerRequired() const override { return true; }
     72 
     73   void emitFrames(MCAsmBackend *MAB);
     74   void emitCFISections(bool EH, bool Debug) override;
     75 
     76   MCFragment *getCurrentFragment() const;
     77 
     78   void insert(MCFragment *F) {
     79     flushPendingLabels(F);
     80     MCSection *CurSection = getCurrentSectionOnly();
     81     CurSection->getFragmentList().insert(CurInsertionPoint, F);
     82     F->setParent(CurSection);
     83   }
     84 
     85   /// Get a data fragment to write into, creating a new one if the current
     86   /// fragment is not a data fragment.
     87   /// Optionally a \p STI can be passed in so that a new fragment is created
     88   /// if the Subtarget differs from the current fragment.
     89   MCDataFragment *getOrCreateDataFragment(const MCSubtargetInfo* STI = nullptr);
     90 
     91 protected:
     92   bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection);
     93 
     94   /// Assign a label to the current Section and Subsection even though a
     95   /// fragment is not yet present. Use flushPendingLabels(F) to associate
     96   /// a fragment with this label.
     97   void addPendingLabel(MCSymbol* label);
     98 
     99   /// If any labels have been emitted but not assigned fragments in the current
    100   /// Section and Subsection, ensure that they get assigned, either to fragment
    101   /// F if possible or to a new data fragment. Optionally, one can provide an
    102   /// offset \p FOffset as a symbol offset within the fragment.
    103   void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0);
    104 
    105 public:
    106   void visitUsedSymbol(const MCSymbol &Sym) override;
    107 
    108   /// Create a data fragment for any pending labels across all Sections
    109   /// and Subsections.
    110   void flushPendingLabels();
    111 
    112   MCAssembler &getAssembler() { return *Assembler; }
    113   MCAssembler *getAssemblerPtr() override;
    114   /// \name MCStreamer Interface
    115   /// @{
    116 
    117   void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
    118   virtual void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment *F,
    119                               uint64_t Offset);
    120   void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
    121   void emitValueImpl(const MCExpr *Value, unsigned Size,
    122                      SMLoc Loc = SMLoc()) override;
    123   void emitULEB128Value(const MCExpr *Value) override;
    124   void emitSLEB128Value(const MCExpr *Value) override;
    125   void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
    126   void changeSection(MCSection *Section, const MCExpr *Subsection) override;
    127   void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
    128 
    129   /// Emit an instruction to a special fragment, because this instruction
    130   /// can change its size during relaxation.
    131   virtual void emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &);
    132 
    133   void emitBundleAlignMode(unsigned AlignPow2) override;
    134   void emitBundleLock(bool AlignToEnd) override;
    135   void emitBundleUnlock() override;
    136   void emitBytes(StringRef Data) override;
    137   void emitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
    138                             unsigned ValueSize = 1,
    139                             unsigned MaxBytesToEmit = 0) override;
    140   void emitCodeAlignment(unsigned ByteAlignment,
    141                          unsigned MaxBytesToEmit = 0) override;
    142   void emitValueToOffset(const MCExpr *Offset, unsigned char Value,
    143                          SMLoc Loc) override;
    144   void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
    145                              unsigned Flags, unsigned Isa,
    146                              unsigned Discriminator,
    147                              StringRef FileName) override;
    148   void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
    149                                 const MCSymbol *Label,
    150                                 unsigned PointerSize) override;
    151   void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override;
    152   void emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
    153                                  const MCSymbol *Label);
    154   void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
    155                           unsigned Column, bool PrologueEnd, bool IsStmt,
    156                           StringRef FileName, SMLoc Loc) override;
    157   void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *Begin,
    158                                 const MCSymbol *End) override;
    159   void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
    160                                       unsigned SourceFileId,
    161                                       unsigned SourceLineNum,
    162                                       const MCSymbol *FnStartSym,
    163                                       const MCSymbol *FnEndSym) override;
    164   void emitCVDefRangeDirective(
    165       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    166       StringRef FixedSizePortion) override;
    167   void emitCVStringTableDirective() override;
    168   void emitCVFileChecksumsDirective() override;
    169   void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
    170   void emitDTPRel32Value(const MCExpr *Value) override;
    171   void emitDTPRel64Value(const MCExpr *Value) override;
    172   void emitTPRel32Value(const MCExpr *Value) override;
    173   void emitTPRel64Value(const MCExpr *Value) override;
    174   void emitGPRel32Value(const MCExpr *Value) override;
    175   void emitGPRel64Value(const MCExpr *Value) override;
    176   Optional<std::pair<bool, std::string>>
    177   emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
    178                      SMLoc Loc, const MCSubtargetInfo &STI) override;
    179   using MCStreamer::emitFill;
    180   void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
    181                 SMLoc Loc = SMLoc()) override;
    182   void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
    183                 SMLoc Loc = SMLoc()) override;
    184   void emitNops(int64_t NumBytes, int64_t ControlledNopLength,
    185                 SMLoc Loc) override;
    186   void emitFileDirective(StringRef Filename) override;
    187 
    188   void emitAddrsig() override;
    189   void emitAddrsigSym(const MCSymbol *Sym) override;
    190 
    191   void finishImpl() override;
    192 
    193   /// Emit the absolute difference between two symbols if possible.
    194   ///
    195   /// Emit the absolute difference between \c Hi and \c Lo, as long as we can
    196   /// compute it.  Currently, that requires that both symbols are in the same
    197   /// data fragment and that the target has not specified that diff expressions
    198   /// require relocations to be emitted. Otherwise, do nothing and return
    199   /// \c false.
    200   ///
    201   /// \pre Offset of \c Hi is greater than the offset \c Lo.
    202   void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
    203                               unsigned Size) override;
    204 
    205   void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
    206                                        const MCSymbol *Lo) override;
    207 
    208   bool mayHaveInstructions(MCSection &Sec) const override;
    209 };
    210 
    211 } // end namespace llvm
    212 
    213 #endif
    214