xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- MCFragment.h - Fragment type hierarchy -------------------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #ifndef LLVM_MC_MCFRAGMENT_H
10*0b57cec5SDimitry Andric #define LLVM_MC_MCFRAGMENT_H
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
13*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
14*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/ilist_node.h"
17*0b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
18*0b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
19*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
20*0b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
21*0b57cec5SDimitry Andric #include <cstdint>
22*0b57cec5SDimitry Andric #include <utility>
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric namespace llvm {
25*0b57cec5SDimitry Andric 
26*0b57cec5SDimitry Andric class MCSection;
27*0b57cec5SDimitry Andric class MCSubtargetInfo;
28*0b57cec5SDimitry Andric class MCSymbol;
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
31*0b57cec5SDimitry Andric   friend class MCAsmLayout;
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric public:
34*0b57cec5SDimitry Andric   enum FragmentType : uint8_t {
35*0b57cec5SDimitry Andric     FT_Align,
36*0b57cec5SDimitry Andric     FT_Data,
37*0b57cec5SDimitry Andric     FT_CompactEncodedInst,
38*0b57cec5SDimitry Andric     FT_Fill,
39*0b57cec5SDimitry Andric     FT_Relaxable,
40*0b57cec5SDimitry Andric     FT_Org,
41*0b57cec5SDimitry Andric     FT_Dwarf,
42*0b57cec5SDimitry Andric     FT_DwarfFrame,
43*0b57cec5SDimitry Andric     FT_LEB,
44*0b57cec5SDimitry Andric     FT_Padding,
45*0b57cec5SDimitry Andric     FT_SymbolId,
46*0b57cec5SDimitry Andric     FT_CVInlineLines,
47*0b57cec5SDimitry Andric     FT_CVDefRange,
48*0b57cec5SDimitry Andric     FT_Dummy
49*0b57cec5SDimitry Andric   };
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric private:
52*0b57cec5SDimitry Andric   FragmentType Kind;
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric protected:
55*0b57cec5SDimitry Andric   bool HasInstructions;
56*0b57cec5SDimitry Andric 
57*0b57cec5SDimitry Andric private:
58*0b57cec5SDimitry Andric   /// LayoutOrder - The layout order of this fragment.
59*0b57cec5SDimitry Andric   unsigned LayoutOrder;
60*0b57cec5SDimitry Andric 
61*0b57cec5SDimitry Andric   /// The data for the section this fragment is in.
62*0b57cec5SDimitry Andric   MCSection *Parent;
63*0b57cec5SDimitry Andric 
64*0b57cec5SDimitry Andric   /// Atom - The atom this fragment is in, as represented by its defining
65*0b57cec5SDimitry Andric   /// symbol.
66*0b57cec5SDimitry Andric   const MCSymbol *Atom;
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric   /// \name Assembler Backend Data
69*0b57cec5SDimitry Andric   /// @{
70*0b57cec5SDimitry Andric   //
71*0b57cec5SDimitry Andric   // FIXME: This could all be kept private to the assembler implementation.
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric   /// Offset - The offset of this fragment in its section. This is ~0 until
74*0b57cec5SDimitry Andric   /// initialized.
75*0b57cec5SDimitry Andric   uint64_t Offset;
76*0b57cec5SDimitry Andric 
77*0b57cec5SDimitry Andric   /// @}
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric protected:
80*0b57cec5SDimitry Andric   MCFragment(FragmentType Kind, bool HasInstructions,
81*0b57cec5SDimitry Andric              MCSection *Parent = nullptr);
82*0b57cec5SDimitry Andric 
83*0b57cec5SDimitry Andric   ~MCFragment();
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric public:
86*0b57cec5SDimitry Andric   MCFragment() = delete;
87*0b57cec5SDimitry Andric   MCFragment(const MCFragment &) = delete;
88*0b57cec5SDimitry Andric   MCFragment &operator=(const MCFragment &) = delete;
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric   /// Destroys the current fragment.
91*0b57cec5SDimitry Andric   ///
92*0b57cec5SDimitry Andric   /// This must be used instead of delete as MCFragment is non-virtual.
93*0b57cec5SDimitry Andric   /// This method will dispatch to the appropriate subclass.
94*0b57cec5SDimitry Andric   void destroy();
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric   FragmentType getKind() const { return Kind; }
97*0b57cec5SDimitry Andric 
98*0b57cec5SDimitry Andric   MCSection *getParent() const { return Parent; }
99*0b57cec5SDimitry Andric   void setParent(MCSection *Value) { Parent = Value; }
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric   const MCSymbol *getAtom() const { return Atom; }
102*0b57cec5SDimitry Andric   void setAtom(const MCSymbol *Value) { Atom = Value; }
103*0b57cec5SDimitry Andric 
104*0b57cec5SDimitry Andric   unsigned getLayoutOrder() const { return LayoutOrder; }
105*0b57cec5SDimitry Andric   void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric   /// Does this fragment have instructions emitted into it? By default
108*0b57cec5SDimitry Andric   /// this is false, but specific fragment types may set it to true.
109*0b57cec5SDimitry Andric   bool hasInstructions() const { return HasInstructions; }
110*0b57cec5SDimitry Andric 
111*0b57cec5SDimitry Andric   /// Return true if given frgment has FT_Dummy type.
112*0b57cec5SDimitry Andric   bool isDummy() const { return Kind == FT_Dummy; }
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric   void dump() const;
115*0b57cec5SDimitry Andric };
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric class MCDummyFragment : public MCFragment {
118*0b57cec5SDimitry Andric public:
119*0b57cec5SDimitry Andric   explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
120*0b57cec5SDimitry Andric 
121*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
122*0b57cec5SDimitry Andric };
123*0b57cec5SDimitry Andric 
124*0b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
125*0b57cec5SDimitry Andric /// data.
126*0b57cec5SDimitry Andric ///
127*0b57cec5SDimitry Andric class MCEncodedFragment : public MCFragment {
128*0b57cec5SDimitry Andric   /// Should this fragment be aligned to the end of a bundle?
129*0b57cec5SDimitry Andric   bool AlignToBundleEnd = false;
130*0b57cec5SDimitry Andric 
131*0b57cec5SDimitry Andric   uint8_t BundlePadding = 0;
132*0b57cec5SDimitry Andric 
133*0b57cec5SDimitry Andric protected:
134*0b57cec5SDimitry Andric   MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
135*0b57cec5SDimitry Andric                     MCSection *Sec)
136*0b57cec5SDimitry Andric       : MCFragment(FType, HasInstructions, Sec) {}
137*0b57cec5SDimitry Andric 
138*0b57cec5SDimitry Andric   /// STI - The MCSubtargetInfo in effect when the instruction was encoded.
139*0b57cec5SDimitry Andric   /// must be non-null for instructions.
140*0b57cec5SDimitry Andric   const MCSubtargetInfo *STI = nullptr;
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric public:
143*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
144*0b57cec5SDimitry Andric     MCFragment::FragmentType Kind = F->getKind();
145*0b57cec5SDimitry Andric     switch (Kind) {
146*0b57cec5SDimitry Andric     default:
147*0b57cec5SDimitry Andric       return false;
148*0b57cec5SDimitry Andric     case MCFragment::FT_Relaxable:
149*0b57cec5SDimitry Andric     case MCFragment::FT_CompactEncodedInst:
150*0b57cec5SDimitry Andric     case MCFragment::FT_Data:
151*0b57cec5SDimitry Andric     case MCFragment::FT_Dwarf:
152*0b57cec5SDimitry Andric     case MCFragment::FT_DwarfFrame:
153*0b57cec5SDimitry Andric       return true;
154*0b57cec5SDimitry Andric     }
155*0b57cec5SDimitry Andric   }
156*0b57cec5SDimitry Andric 
157*0b57cec5SDimitry Andric   /// Should this fragment be placed at the end of an aligned bundle?
158*0b57cec5SDimitry Andric   bool alignToBundleEnd() const { return AlignToBundleEnd; }
159*0b57cec5SDimitry Andric   void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
160*0b57cec5SDimitry Andric 
161*0b57cec5SDimitry Andric   /// Get the padding size that must be inserted before this fragment.
162*0b57cec5SDimitry Andric   /// Used for bundling. By default, no padding is inserted.
163*0b57cec5SDimitry Andric   /// Note that padding size is restricted to 8 bits. This is an optimization
164*0b57cec5SDimitry Andric   /// to reduce the amount of space used for each fragment. In practice, larger
165*0b57cec5SDimitry Andric   /// padding should never be required.
166*0b57cec5SDimitry Andric   uint8_t getBundlePadding() const { return BundlePadding; }
167*0b57cec5SDimitry Andric 
168*0b57cec5SDimitry Andric   /// Set the padding size for this fragment. By default it's a no-op,
169*0b57cec5SDimitry Andric   /// and only some fragments have a meaningful implementation.
170*0b57cec5SDimitry Andric   void setBundlePadding(uint8_t N) { BundlePadding = N; }
171*0b57cec5SDimitry Andric 
172*0b57cec5SDimitry Andric   /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
173*0b57cec5SDimitry Andric   /// Guaranteed to be non-null if hasInstructions() == true
174*0b57cec5SDimitry Andric   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
175*0b57cec5SDimitry Andric 
176*0b57cec5SDimitry Andric   /// Record that the fragment contains instructions with the MCSubtargetInfo in
177*0b57cec5SDimitry Andric   /// effect when the instruction was encoded.
178*0b57cec5SDimitry Andric   void setHasInstructions(const MCSubtargetInfo &STI) {
179*0b57cec5SDimitry Andric     HasInstructions = true;
180*0b57cec5SDimitry Andric     this->STI = &STI;
181*0b57cec5SDimitry Andric   }
182*0b57cec5SDimitry Andric };
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
185*0b57cec5SDimitry Andric /// data.
186*0b57cec5SDimitry Andric ///
187*0b57cec5SDimitry Andric template<unsigned ContentsSize>
188*0b57cec5SDimitry Andric class MCEncodedFragmentWithContents : public MCEncodedFragment {
189*0b57cec5SDimitry Andric   SmallVector<char, ContentsSize> Contents;
190*0b57cec5SDimitry Andric 
191*0b57cec5SDimitry Andric protected:
192*0b57cec5SDimitry Andric   MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
193*0b57cec5SDimitry Andric                                 bool HasInstructions,
194*0b57cec5SDimitry Andric                                 MCSection *Sec)
195*0b57cec5SDimitry Andric       : MCEncodedFragment(FType, HasInstructions, Sec) {}
196*0b57cec5SDimitry Andric 
197*0b57cec5SDimitry Andric public:
198*0b57cec5SDimitry Andric   SmallVectorImpl<char> &getContents() { return Contents; }
199*0b57cec5SDimitry Andric   const SmallVectorImpl<char> &getContents() const { return Contents; }
200*0b57cec5SDimitry Andric };
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric /// Interface implemented by fragments that contain encoded instructions and/or
203*0b57cec5SDimitry Andric /// data and also have fixups registered.
204*0b57cec5SDimitry Andric ///
205*0b57cec5SDimitry Andric template<unsigned ContentsSize, unsigned FixupsSize>
206*0b57cec5SDimitry Andric class MCEncodedFragmentWithFixups :
207*0b57cec5SDimitry Andric   public MCEncodedFragmentWithContents<ContentsSize> {
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric   /// Fixups - The list of fixups in this fragment.
210*0b57cec5SDimitry Andric   SmallVector<MCFixup, FixupsSize> Fixups;
211*0b57cec5SDimitry Andric 
212*0b57cec5SDimitry Andric protected:
213*0b57cec5SDimitry Andric   MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
214*0b57cec5SDimitry Andric                               bool HasInstructions,
215*0b57cec5SDimitry Andric                               MCSection *Sec)
216*0b57cec5SDimitry Andric       : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
217*0b57cec5SDimitry Andric                                                     Sec) {}
218*0b57cec5SDimitry Andric 
219*0b57cec5SDimitry Andric public:
220*0b57cec5SDimitry Andric 
221*0b57cec5SDimitry Andric   using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
222*0b57cec5SDimitry Andric   using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
223*0b57cec5SDimitry Andric 
224*0b57cec5SDimitry Andric   SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
225*0b57cec5SDimitry Andric   const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
226*0b57cec5SDimitry Andric 
227*0b57cec5SDimitry Andric   fixup_iterator fixup_begin() { return Fixups.begin(); }
228*0b57cec5SDimitry Andric   const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
229*0b57cec5SDimitry Andric 
230*0b57cec5SDimitry Andric   fixup_iterator fixup_end() { return Fixups.end(); }
231*0b57cec5SDimitry Andric   const_fixup_iterator fixup_end() const { return Fixups.end(); }
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
234*0b57cec5SDimitry Andric     MCFragment::FragmentType Kind = F->getKind();
235*0b57cec5SDimitry Andric     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
236*0b57cec5SDimitry Andric            Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
237*0b57cec5SDimitry Andric            Kind == MCFragment::FT_DwarfFrame;
238*0b57cec5SDimitry Andric   }
239*0b57cec5SDimitry Andric };
240*0b57cec5SDimitry Andric 
241*0b57cec5SDimitry Andric /// Fragment for data and encoded instructions.
242*0b57cec5SDimitry Andric ///
243*0b57cec5SDimitry Andric class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
244*0b57cec5SDimitry Andric public:
245*0b57cec5SDimitry Andric   MCDataFragment(MCSection *Sec = nullptr)
246*0b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
247*0b57cec5SDimitry Andric 
248*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
249*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Data;
250*0b57cec5SDimitry Andric   }
251*0b57cec5SDimitry Andric };
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric /// This is a compact (memory-size-wise) fragment for holding an encoded
254*0b57cec5SDimitry Andric /// instruction (non-relaxable) that has no fixups registered. When applicable,
255*0b57cec5SDimitry Andric /// it can be used instead of MCDataFragment and lead to lower memory
256*0b57cec5SDimitry Andric /// consumption.
257*0b57cec5SDimitry Andric ///
258*0b57cec5SDimitry Andric class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
259*0b57cec5SDimitry Andric public:
260*0b57cec5SDimitry Andric   MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
261*0b57cec5SDimitry Andric       : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
262*0b57cec5SDimitry Andric   }
263*0b57cec5SDimitry Andric 
264*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
265*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CompactEncodedInst;
266*0b57cec5SDimitry Andric   }
267*0b57cec5SDimitry Andric };
268*0b57cec5SDimitry Andric 
269*0b57cec5SDimitry Andric /// A relaxable fragment holds on to its MCInst, since it may need to be
270*0b57cec5SDimitry Andric /// relaxed during the assembler layout and relaxation stage.
271*0b57cec5SDimitry Andric ///
272*0b57cec5SDimitry Andric class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
273*0b57cec5SDimitry Andric 
274*0b57cec5SDimitry Andric   /// Inst - The instruction this is a fragment for.
275*0b57cec5SDimitry Andric   MCInst Inst;
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric public:
278*0b57cec5SDimitry Andric   MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
279*0b57cec5SDimitry Andric                       MCSection *Sec = nullptr)
280*0b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
281*0b57cec5SDimitry Andric         Inst(Inst) { this->STI = &STI; }
282*0b57cec5SDimitry Andric 
283*0b57cec5SDimitry Andric   const MCInst &getInst() const { return Inst; }
284*0b57cec5SDimitry Andric   void setInst(const MCInst &Value) { Inst = Value; }
285*0b57cec5SDimitry Andric 
286*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
287*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Relaxable;
288*0b57cec5SDimitry Andric   }
289*0b57cec5SDimitry Andric };
290*0b57cec5SDimitry Andric 
291*0b57cec5SDimitry Andric class MCAlignFragment : public MCFragment {
292*0b57cec5SDimitry Andric   /// Alignment - The alignment to ensure, in bytes.
293*0b57cec5SDimitry Andric   unsigned Alignment;
294*0b57cec5SDimitry Andric 
295*0b57cec5SDimitry Andric   /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead
296*0b57cec5SDimitry Andric   /// of using the provided value. The exact interpretation of this flag is
297*0b57cec5SDimitry Andric   /// target dependent.
298*0b57cec5SDimitry Andric   bool EmitNops : 1;
299*0b57cec5SDimitry Andric 
300*0b57cec5SDimitry Andric   /// Value - Value to use for filling padding bytes.
301*0b57cec5SDimitry Andric   int64_t Value;
302*0b57cec5SDimitry Andric 
303*0b57cec5SDimitry Andric   /// ValueSize - The size of the integer (in bytes) of \p Value.
304*0b57cec5SDimitry Andric   unsigned ValueSize;
305*0b57cec5SDimitry Andric 
306*0b57cec5SDimitry Andric   /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment
307*0b57cec5SDimitry Andric   /// cannot be satisfied in this width then this fragment is ignored.
308*0b57cec5SDimitry Andric   unsigned MaxBytesToEmit;
309*0b57cec5SDimitry Andric 
310*0b57cec5SDimitry Andric public:
311*0b57cec5SDimitry Andric   MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
312*0b57cec5SDimitry Andric                   unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
313*0b57cec5SDimitry Andric       : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
314*0b57cec5SDimitry Andric         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
315*0b57cec5SDimitry Andric 
316*0b57cec5SDimitry Andric   /// \name Accessors
317*0b57cec5SDimitry Andric   /// @{
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric   unsigned getAlignment() const { return Alignment; }
320*0b57cec5SDimitry Andric 
321*0b57cec5SDimitry Andric   int64_t getValue() const { return Value; }
322*0b57cec5SDimitry Andric 
323*0b57cec5SDimitry Andric   unsigned getValueSize() const { return ValueSize; }
324*0b57cec5SDimitry Andric 
325*0b57cec5SDimitry Andric   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
326*0b57cec5SDimitry Andric 
327*0b57cec5SDimitry Andric   bool hasEmitNops() const { return EmitNops; }
328*0b57cec5SDimitry Andric   void setEmitNops(bool Value) { EmitNops = Value; }
329*0b57cec5SDimitry Andric 
330*0b57cec5SDimitry Andric   /// @}
331*0b57cec5SDimitry Andric 
332*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
333*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Align;
334*0b57cec5SDimitry Andric   }
335*0b57cec5SDimitry Andric };
336*0b57cec5SDimitry Andric 
337*0b57cec5SDimitry Andric /// Fragment for adding required padding.
338*0b57cec5SDimitry Andric /// This fragment is always inserted before an instruction, and holds that
339*0b57cec5SDimitry Andric /// instruction as context information (as well as a mask of kinds) for
340*0b57cec5SDimitry Andric /// determining the padding size.
341*0b57cec5SDimitry Andric ///
342*0b57cec5SDimitry Andric class MCPaddingFragment : public MCFragment {
343*0b57cec5SDimitry Andric   /// A mask containing all the kinds relevant to this fragment. i.e. the i'th
344*0b57cec5SDimitry Andric   /// bit will be set iff kind i is relevant to this fragment.
345*0b57cec5SDimitry Andric   uint64_t PaddingPoliciesMask;
346*0b57cec5SDimitry Andric   /// A boolean indicating if this fragment will actually hold padding. If its
347*0b57cec5SDimitry Andric   /// value is false, then this fragment serves only as a placeholder,
348*0b57cec5SDimitry Andric   /// containing data to assist other insertion point in their decision making.
349*0b57cec5SDimitry Andric   bool IsInsertionPoint;
350*0b57cec5SDimitry Andric 
351*0b57cec5SDimitry Andric   uint64_t Size;
352*0b57cec5SDimitry Andric 
353*0b57cec5SDimitry Andric   struct MCInstInfo {
354*0b57cec5SDimitry Andric     bool IsInitialized;
355*0b57cec5SDimitry Andric     MCInst Inst;
356*0b57cec5SDimitry Andric     /// A boolean indicating whether the instruction pointed by this fragment is
357*0b57cec5SDimitry Andric     /// a fixed size instruction or a relaxable instruction held by a
358*0b57cec5SDimitry Andric     /// MCRelaxableFragment.
359*0b57cec5SDimitry Andric     bool IsImmutableSizedInst;
360*0b57cec5SDimitry Andric     union {
361*0b57cec5SDimitry Andric       /// If the instruction is a fixed size instruction, hold its size.
362*0b57cec5SDimitry Andric       size_t InstSize;
363*0b57cec5SDimitry Andric       /// Otherwise, hold a pointer to the MCRelaxableFragment holding it.
364*0b57cec5SDimitry Andric       MCRelaxableFragment *InstFragment;
365*0b57cec5SDimitry Andric     };
366*0b57cec5SDimitry Andric   };
367*0b57cec5SDimitry Andric   MCInstInfo InstInfo;
368*0b57cec5SDimitry Andric 
369*0b57cec5SDimitry Andric public:
370*0b57cec5SDimitry Andric   static const uint64_t PFK_None = UINT64_C(0);
371*0b57cec5SDimitry Andric 
372*0b57cec5SDimitry Andric   enum MCPaddingFragmentKind {
373*0b57cec5SDimitry Andric     // values 0-7 are reserved for future target independet values.
374*0b57cec5SDimitry Andric 
375*0b57cec5SDimitry Andric     FirstTargetPerfNopFragmentKind = 8,
376*0b57cec5SDimitry Andric 
377*0b57cec5SDimitry Andric     /// Limit range of target MCPerfNopFragment kinds to fit in uint64_t
378*0b57cec5SDimitry Andric     MaxTargetPerfNopFragmentKind = 63
379*0b57cec5SDimitry Andric   };
380*0b57cec5SDimitry Andric 
381*0b57cec5SDimitry Andric   MCPaddingFragment(MCSection *Sec = nullptr)
382*0b57cec5SDimitry Andric       : MCFragment(FT_Padding, false, Sec), PaddingPoliciesMask(PFK_None),
383*0b57cec5SDimitry Andric         IsInsertionPoint(false), Size(UINT64_C(0)),
384*0b57cec5SDimitry Andric         InstInfo({false, MCInst(), false, {0}}) {}
385*0b57cec5SDimitry Andric 
386*0b57cec5SDimitry Andric   bool isInsertionPoint() const { return IsInsertionPoint; }
387*0b57cec5SDimitry Andric   void setAsInsertionPoint() { IsInsertionPoint = true; }
388*0b57cec5SDimitry Andric   uint64_t getPaddingPoliciesMask() const { return PaddingPoliciesMask; }
389*0b57cec5SDimitry Andric   void setPaddingPoliciesMask(uint64_t Value) { PaddingPoliciesMask = Value; }
390*0b57cec5SDimitry Andric   bool hasPaddingPolicy(uint64_t PolicyMask) const {
391*0b57cec5SDimitry Andric     assert(isPowerOf2_64(PolicyMask) &&
392*0b57cec5SDimitry Andric            "Policy mask must contain exactly one policy");
393*0b57cec5SDimitry Andric     return (getPaddingPoliciesMask() & PolicyMask) != PFK_None;
394*0b57cec5SDimitry Andric   }
395*0b57cec5SDimitry Andric   const MCInst &getInst() const {
396*0b57cec5SDimitry Andric     assert(isInstructionInitialized() && "Fragment has no instruction!");
397*0b57cec5SDimitry Andric     return InstInfo.Inst;
398*0b57cec5SDimitry Andric   }
399*0b57cec5SDimitry Andric   size_t getInstSize() const {
400*0b57cec5SDimitry Andric     assert(isInstructionInitialized() && "Fragment has no instruction!");
401*0b57cec5SDimitry Andric     if (InstInfo.IsImmutableSizedInst)
402*0b57cec5SDimitry Andric       return InstInfo.InstSize;
403*0b57cec5SDimitry Andric     assert(InstInfo.InstFragment != nullptr &&
404*0b57cec5SDimitry Andric            "Must have a valid InstFragment to retrieve InstSize from");
405*0b57cec5SDimitry Andric     return InstInfo.InstFragment->getContents().size();
406*0b57cec5SDimitry Andric   }
407*0b57cec5SDimitry Andric   void setInstAndInstSize(const MCInst &Inst, size_t InstSize) {
408*0b57cec5SDimitry Andric 	InstInfo.IsInitialized = true;
409*0b57cec5SDimitry Andric     InstInfo.IsImmutableSizedInst = true;
410*0b57cec5SDimitry Andric     InstInfo.Inst = Inst;
411*0b57cec5SDimitry Andric     InstInfo.InstSize = InstSize;
412*0b57cec5SDimitry Andric   }
413*0b57cec5SDimitry Andric   void setInstAndInstFragment(const MCInst &Inst,
414*0b57cec5SDimitry Andric                               MCRelaxableFragment *InstFragment) {
415*0b57cec5SDimitry Andric     InstInfo.IsInitialized = true;
416*0b57cec5SDimitry Andric     InstInfo.IsImmutableSizedInst = false;
417*0b57cec5SDimitry Andric     InstInfo.Inst = Inst;
418*0b57cec5SDimitry Andric     InstInfo.InstFragment = InstFragment;
419*0b57cec5SDimitry Andric   }
420*0b57cec5SDimitry Andric   uint64_t getSize() const { return Size; }
421*0b57cec5SDimitry Andric   void setSize(uint64_t Value) { Size = Value; }
422*0b57cec5SDimitry Andric   bool isInstructionInitialized() const { return InstInfo.IsInitialized; }
423*0b57cec5SDimitry Andric 
424*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
425*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Padding;
426*0b57cec5SDimitry Andric   }
427*0b57cec5SDimitry Andric };
428*0b57cec5SDimitry Andric 
429*0b57cec5SDimitry Andric class MCFillFragment : public MCFragment {
430*0b57cec5SDimitry Andric   /// Value to use for filling bytes.
431*0b57cec5SDimitry Andric   uint64_t Value;
432*0b57cec5SDimitry Andric   uint8_t ValueSize;
433*0b57cec5SDimitry Andric   /// The number of bytes to insert.
434*0b57cec5SDimitry Andric   const MCExpr &NumValues;
435*0b57cec5SDimitry Andric 
436*0b57cec5SDimitry Andric   /// Source location of the directive that this fragment was created for.
437*0b57cec5SDimitry Andric   SMLoc Loc;
438*0b57cec5SDimitry Andric 
439*0b57cec5SDimitry Andric public:
440*0b57cec5SDimitry Andric   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
441*0b57cec5SDimitry Andric                  SMLoc Loc, MCSection *Sec = nullptr)
442*0b57cec5SDimitry Andric       : MCFragment(FT_Fill, false, Sec), Value(Value), ValueSize(VSize),
443*0b57cec5SDimitry Andric         NumValues(NumValues), Loc(Loc) {}
444*0b57cec5SDimitry Andric 
445*0b57cec5SDimitry Andric   uint64_t getValue() const { return Value; }
446*0b57cec5SDimitry Andric   uint8_t getValueSize() const { return ValueSize; }
447*0b57cec5SDimitry Andric   const MCExpr &getNumValues() const { return NumValues; }
448*0b57cec5SDimitry Andric 
449*0b57cec5SDimitry Andric   SMLoc getLoc() const { return Loc; }
450*0b57cec5SDimitry Andric 
451*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
452*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Fill;
453*0b57cec5SDimitry Andric   }
454*0b57cec5SDimitry Andric };
455*0b57cec5SDimitry Andric 
456*0b57cec5SDimitry Andric class MCOrgFragment : public MCFragment {
457*0b57cec5SDimitry Andric   /// The offset this fragment should start at.
458*0b57cec5SDimitry Andric   const MCExpr *Offset;
459*0b57cec5SDimitry Andric 
460*0b57cec5SDimitry Andric   /// Value to use for filling bytes.
461*0b57cec5SDimitry Andric   int8_t Value;
462*0b57cec5SDimitry Andric 
463*0b57cec5SDimitry Andric   /// Source location of the directive that this fragment was created for.
464*0b57cec5SDimitry Andric   SMLoc Loc;
465*0b57cec5SDimitry Andric 
466*0b57cec5SDimitry Andric public:
467*0b57cec5SDimitry Andric   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
468*0b57cec5SDimitry Andric                 MCSection *Sec = nullptr)
469*0b57cec5SDimitry Andric       : MCFragment(FT_Org, false, Sec), Offset(&Offset), Value(Value), Loc(Loc) {}
470*0b57cec5SDimitry Andric 
471*0b57cec5SDimitry Andric   /// \name Accessors
472*0b57cec5SDimitry Andric   /// @{
473*0b57cec5SDimitry Andric 
474*0b57cec5SDimitry Andric   const MCExpr &getOffset() const { return *Offset; }
475*0b57cec5SDimitry Andric 
476*0b57cec5SDimitry Andric   uint8_t getValue() const { return Value; }
477*0b57cec5SDimitry Andric 
478*0b57cec5SDimitry Andric   SMLoc getLoc() const { return Loc; }
479*0b57cec5SDimitry Andric 
480*0b57cec5SDimitry Andric   /// @}
481*0b57cec5SDimitry Andric 
482*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
483*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Org;
484*0b57cec5SDimitry Andric   }
485*0b57cec5SDimitry Andric };
486*0b57cec5SDimitry Andric 
487*0b57cec5SDimitry Andric class MCLEBFragment : public MCFragment {
488*0b57cec5SDimitry Andric   /// Value - The value this fragment should contain.
489*0b57cec5SDimitry Andric   const MCExpr *Value;
490*0b57cec5SDimitry Andric 
491*0b57cec5SDimitry Andric   /// IsSigned - True if this is a sleb128, false if uleb128.
492*0b57cec5SDimitry Andric   bool IsSigned;
493*0b57cec5SDimitry Andric 
494*0b57cec5SDimitry Andric   SmallString<8> Contents;
495*0b57cec5SDimitry Andric 
496*0b57cec5SDimitry Andric public:
497*0b57cec5SDimitry Andric   MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
498*0b57cec5SDimitry Andric       : MCFragment(FT_LEB, false, Sec), Value(&Value_), IsSigned(IsSigned_) {
499*0b57cec5SDimitry Andric     Contents.push_back(0);
500*0b57cec5SDimitry Andric   }
501*0b57cec5SDimitry Andric 
502*0b57cec5SDimitry Andric   /// \name Accessors
503*0b57cec5SDimitry Andric   /// @{
504*0b57cec5SDimitry Andric 
505*0b57cec5SDimitry Andric   const MCExpr &getValue() const { return *Value; }
506*0b57cec5SDimitry Andric 
507*0b57cec5SDimitry Andric   bool isSigned() const { return IsSigned; }
508*0b57cec5SDimitry Andric 
509*0b57cec5SDimitry Andric   SmallString<8> &getContents() { return Contents; }
510*0b57cec5SDimitry Andric   const SmallString<8> &getContents() const { return Contents; }
511*0b57cec5SDimitry Andric 
512*0b57cec5SDimitry Andric   /// @}
513*0b57cec5SDimitry Andric 
514*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
515*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_LEB;
516*0b57cec5SDimitry Andric   }
517*0b57cec5SDimitry Andric };
518*0b57cec5SDimitry Andric 
519*0b57cec5SDimitry Andric class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
520*0b57cec5SDimitry Andric   /// LineDelta - the value of the difference between the two line numbers
521*0b57cec5SDimitry Andric   /// between two .loc dwarf directives.
522*0b57cec5SDimitry Andric   int64_t LineDelta;
523*0b57cec5SDimitry Andric 
524*0b57cec5SDimitry Andric   /// AddrDelta - The expression for the difference of the two symbols that
525*0b57cec5SDimitry Andric   /// make up the address delta between two .loc dwarf directives.
526*0b57cec5SDimitry Andric   const MCExpr *AddrDelta;
527*0b57cec5SDimitry Andric 
528*0b57cec5SDimitry Andric public:
529*0b57cec5SDimitry Andric   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
530*0b57cec5SDimitry Andric                           MCSection *Sec = nullptr)
531*0b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
532*0b57cec5SDimitry Andric         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
533*0b57cec5SDimitry Andric 
534*0b57cec5SDimitry Andric   /// \name Accessors
535*0b57cec5SDimitry Andric   /// @{
536*0b57cec5SDimitry Andric 
537*0b57cec5SDimitry Andric   int64_t getLineDelta() const { return LineDelta; }
538*0b57cec5SDimitry Andric 
539*0b57cec5SDimitry Andric   const MCExpr &getAddrDelta() const { return *AddrDelta; }
540*0b57cec5SDimitry Andric 
541*0b57cec5SDimitry Andric   /// @}
542*0b57cec5SDimitry Andric 
543*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
544*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_Dwarf;
545*0b57cec5SDimitry Andric   }
546*0b57cec5SDimitry Andric };
547*0b57cec5SDimitry Andric 
548*0b57cec5SDimitry Andric class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
549*0b57cec5SDimitry Andric   /// AddrDelta - The expression for the difference of the two symbols that
550*0b57cec5SDimitry Andric   /// make up the address delta between two .cfi_* dwarf directives.
551*0b57cec5SDimitry Andric   const MCExpr *AddrDelta;
552*0b57cec5SDimitry Andric 
553*0b57cec5SDimitry Andric public:
554*0b57cec5SDimitry Andric   MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
555*0b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
556*0b57cec5SDimitry Andric         AddrDelta(&AddrDelta) {}
557*0b57cec5SDimitry Andric 
558*0b57cec5SDimitry Andric   /// \name Accessors
559*0b57cec5SDimitry Andric   /// @{
560*0b57cec5SDimitry Andric 
561*0b57cec5SDimitry Andric   const MCExpr &getAddrDelta() const { return *AddrDelta; }
562*0b57cec5SDimitry Andric 
563*0b57cec5SDimitry Andric   /// @}
564*0b57cec5SDimitry Andric 
565*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
566*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_DwarfFrame;
567*0b57cec5SDimitry Andric   }
568*0b57cec5SDimitry Andric };
569*0b57cec5SDimitry Andric 
570*0b57cec5SDimitry Andric /// Represents a symbol table index fragment.
571*0b57cec5SDimitry Andric class MCSymbolIdFragment : public MCFragment {
572*0b57cec5SDimitry Andric   const MCSymbol *Sym;
573*0b57cec5SDimitry Andric 
574*0b57cec5SDimitry Andric public:
575*0b57cec5SDimitry Andric   MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
576*0b57cec5SDimitry Andric       : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
577*0b57cec5SDimitry Andric 
578*0b57cec5SDimitry Andric   /// \name Accessors
579*0b57cec5SDimitry Andric   /// @{
580*0b57cec5SDimitry Andric 
581*0b57cec5SDimitry Andric   const MCSymbol *getSymbol() { return Sym; }
582*0b57cec5SDimitry Andric   const MCSymbol *getSymbol() const { return Sym; }
583*0b57cec5SDimitry Andric 
584*0b57cec5SDimitry Andric   /// @}
585*0b57cec5SDimitry Andric 
586*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
587*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_SymbolId;
588*0b57cec5SDimitry Andric   }
589*0b57cec5SDimitry Andric };
590*0b57cec5SDimitry Andric 
591*0b57cec5SDimitry Andric /// Fragment representing the binary annotations produced by the
592*0b57cec5SDimitry Andric /// .cv_inline_linetable directive.
593*0b57cec5SDimitry Andric class MCCVInlineLineTableFragment : public MCFragment {
594*0b57cec5SDimitry Andric   unsigned SiteFuncId;
595*0b57cec5SDimitry Andric   unsigned StartFileId;
596*0b57cec5SDimitry Andric   unsigned StartLineNum;
597*0b57cec5SDimitry Andric   const MCSymbol *FnStartSym;
598*0b57cec5SDimitry Andric   const MCSymbol *FnEndSym;
599*0b57cec5SDimitry Andric   SmallString<8> Contents;
600*0b57cec5SDimitry Andric 
601*0b57cec5SDimitry Andric   /// CodeViewContext has the real knowledge about this format, so let it access
602*0b57cec5SDimitry Andric   /// our members.
603*0b57cec5SDimitry Andric   friend class CodeViewContext;
604*0b57cec5SDimitry Andric 
605*0b57cec5SDimitry Andric public:
606*0b57cec5SDimitry Andric   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
607*0b57cec5SDimitry Andric                               unsigned StartLineNum, const MCSymbol *FnStartSym,
608*0b57cec5SDimitry Andric                               const MCSymbol *FnEndSym,
609*0b57cec5SDimitry Andric                               MCSection *Sec = nullptr)
610*0b57cec5SDimitry Andric       : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
611*0b57cec5SDimitry Andric         StartFileId(StartFileId), StartLineNum(StartLineNum),
612*0b57cec5SDimitry Andric         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
613*0b57cec5SDimitry Andric 
614*0b57cec5SDimitry Andric   /// \name Accessors
615*0b57cec5SDimitry Andric   /// @{
616*0b57cec5SDimitry Andric 
617*0b57cec5SDimitry Andric   const MCSymbol *getFnStartSym() const { return FnStartSym; }
618*0b57cec5SDimitry Andric   const MCSymbol *getFnEndSym() const { return FnEndSym; }
619*0b57cec5SDimitry Andric 
620*0b57cec5SDimitry Andric   SmallString<8> &getContents() { return Contents; }
621*0b57cec5SDimitry Andric   const SmallString<8> &getContents() const { return Contents; }
622*0b57cec5SDimitry Andric 
623*0b57cec5SDimitry Andric   /// @}
624*0b57cec5SDimitry Andric 
625*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
626*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CVInlineLines;
627*0b57cec5SDimitry Andric   }
628*0b57cec5SDimitry Andric };
629*0b57cec5SDimitry Andric 
630*0b57cec5SDimitry Andric /// Fragment representing the .cv_def_range directive.
631*0b57cec5SDimitry Andric class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
632*0b57cec5SDimitry Andric   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
633*0b57cec5SDimitry Andric   SmallString<32> FixedSizePortion;
634*0b57cec5SDimitry Andric 
635*0b57cec5SDimitry Andric   /// CodeViewContext has the real knowledge about this format, so let it access
636*0b57cec5SDimitry Andric   /// our members.
637*0b57cec5SDimitry Andric   friend class CodeViewContext;
638*0b57cec5SDimitry Andric 
639*0b57cec5SDimitry Andric public:
640*0b57cec5SDimitry Andric   MCCVDefRangeFragment(
641*0b57cec5SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
642*0b57cec5SDimitry Andric       StringRef FixedSizePortion, MCSection *Sec = nullptr)
643*0b57cec5SDimitry Andric       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
644*0b57cec5SDimitry Andric         Ranges(Ranges.begin(), Ranges.end()),
645*0b57cec5SDimitry Andric         FixedSizePortion(FixedSizePortion) {}
646*0b57cec5SDimitry Andric 
647*0b57cec5SDimitry Andric   /// \name Accessors
648*0b57cec5SDimitry Andric   /// @{
649*0b57cec5SDimitry Andric   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
650*0b57cec5SDimitry Andric     return Ranges;
651*0b57cec5SDimitry Andric   }
652*0b57cec5SDimitry Andric 
653*0b57cec5SDimitry Andric   StringRef getFixedSizePortion() const { return FixedSizePortion; }
654*0b57cec5SDimitry Andric   /// @}
655*0b57cec5SDimitry Andric 
656*0b57cec5SDimitry Andric   static bool classof(const MCFragment *F) {
657*0b57cec5SDimitry Andric     return F->getKind() == MCFragment::FT_CVDefRange;
658*0b57cec5SDimitry Andric   }
659*0b57cec5SDimitry Andric };
660*0b57cec5SDimitry Andric 
661*0b57cec5SDimitry Andric } // end namespace llvm
662*0b57cec5SDimitry Andric 
663*0b57cec5SDimitry Andric #endif // LLVM_MC_MCFRAGMENT_H
664