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