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
19namespace llvm {
20class MCContext;
21class MCInst;
22class MCObjectWriter;
23class MCSymbol;
24struct MCDwarfFrameInfo;
25class MCAssembler;
26class MCCodeEmitter;
27class MCSubtargetInfo;
28class MCExpr;
29class MCFragment;
30class MCDataFragment;
31class MCAsmBackend;
32class raw_ostream;
33class 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.
42class 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 = 0;
50 struct PendingMCFixup {
51 const MCSymbol *Sym;
52 MCFixup Fixup;
53 MCDataFragment *DF;
54 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
76protected:
77 MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
78 std::unique_ptr<MCObjectWriter> OW,
79 std::unique_ptr<MCCodeEmitter> Emitter);
80 ~MCObjectStreamer();
81
82public:
83 /// state management
84 void reset() override;
85
86 /// Object streamers require the integrated assembler.
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
94 void insert(MCFragment *F) {
95 flushPendingLabels(F);
96 MCSection *CurSection = getCurrentSectionOnly();
97 CurSection->getFragmentList().insert(where: CurInsertionPoint, New: 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
107protected:
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 to fragment F.
117 /// Optionally, one can provide an offset \p FOffset as a symbol offset within
118 /// the fragment.
119 void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0);
120
121public:
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
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, SMLoc Loc);
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 CompilerVersion,
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

source code of llvm/include/llvm/MC/MCObjectStreamer.h