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;
PendingMCFixupPendingMCFixup48     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.
isIntegratedAssemblerRequired()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 
insert(MCFragment * F)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 
getAssembler()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   void emitFileDirective(StringRef Filename, StringRef CompilerVerion,
188                          StringRef TimeStamp, StringRef Description) override;
189 
190   void emitAddrsig() override;
191   void emitAddrsigSym(const MCSymbol *Sym) override;
192 
193   void finishImpl() override;
194 
195   /// Emit the absolute difference between two symbols if possible.
196   ///
197   /// Emit the absolute difference between \c Hi and \c Lo, as long as we can
198   /// compute it.  Currently, that requires that both symbols are in the same
199   /// data fragment and that the target has not specified that diff expressions
200   /// require relocations to be emitted. Otherwise, do nothing and return
201   /// \c false.
202   ///
203   /// \pre Offset of \c Hi is greater than the offset \c Lo.
204   void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
205                               unsigned Size) override;
206 
207   void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
208                                        const MCSymbol *Lo) override;
209 
210   bool mayHaveInstructions(MCSection &Sec) const override;
211 };
212 
213 } // end namespace llvm
214 
215 #endif
216