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