1 //===- llvm/MC/MCAsmBackend.h - MC Asm Backend ------------------*- 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_MCASMBACKEND_H
10 #define LLVM_MC_MCASMBACKEND_H
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/Optional.h"
14 #include "llvm/MC/MCDirectives.h"
15 #include "llvm/MC/MCFixup.h"
16 #include "llvm/MC/MCFragment.h"
17 #include "llvm/Support/Endian.h"
18 #include <cstdint>
19 
20 namespace llvm {
21 
22 class MCAsmLayout;
23 class MCAssembler;
24 class MCCFIInstruction;
25 struct MCFixupKindInfo;
26 class MCInst;
27 class MCObjectStreamer;
28 class MCObjectTargetWriter;
29 class MCObjectWriter;
30 class MCSubtargetInfo;
31 class MCValue;
32 class raw_pwrite_stream;
33 class StringRef;
34 
35 /// Generic interface to target specific assembler backends.
36 class MCAsmBackend {
37 protected: // Can only create subclasses.
38   MCAsmBackend(support::endianness Endian);
39 
40 public:
41   MCAsmBackend(const MCAsmBackend &) = delete;
42   MCAsmBackend &operator=(const MCAsmBackend &) = delete;
43   virtual ~MCAsmBackend();
44 
45   const support::endianness Endian;
46 
47   /// Return true if this target might automatically pad instructions and thus
48   /// need to emit padding enable/disable directives around sensative code.
allowAutoPadding()49   virtual bool allowAutoPadding() const { return false; }
50   /// Return true if this target allows an unrelaxable instruction to be
51   /// emitted into RelaxableFragment and then we can increase its size in a
52   /// tricky way for optimization.
allowEnhancedRelaxation()53   virtual bool allowEnhancedRelaxation() const { return false; }
54 
55   /// Give the target a chance to manipulate state related to instruction
56   /// alignment (e.g. padding for optimization), instruction relaxablility, etc.
57   /// before and after actually emitting the instruction.
emitInstructionBegin(MCObjectStreamer & OS,const MCInst & Inst,const MCSubtargetInfo & STI)58   virtual void emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst,
59                                     const MCSubtargetInfo &STI) {}
emitInstructionEnd(MCObjectStreamer & OS,const MCInst & Inst)60   virtual void emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) {}
61 
62   /// lifetime management
reset()63   virtual void reset() {}
64 
65   /// Create a new MCObjectWriter instance for use by the assembler backend to
66   /// emit the final object file.
67   std::unique_ptr<MCObjectWriter>
68   createObjectWriter(raw_pwrite_stream &OS) const;
69 
70   /// Create an MCObjectWriter that writes two object files: a .o file which is
71   /// linked into the final program and a .dwo file which is used by debuggers.
72   /// This function is only supported with ELF targets.
73   std::unique_ptr<MCObjectWriter>
74   createDwoObjectWriter(raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS) const;
75 
76   virtual std::unique_ptr<MCObjectTargetWriter>
77   createObjectTargetWriter() const = 0;
78 
79   /// \name Target Fixup Interfaces
80   /// @{
81 
82   /// Get the number of target specific fixup kinds.
83   virtual unsigned getNumFixupKinds() const = 0;
84 
85   /// Map a relocation name used in .reloc to a fixup kind.
86   virtual Optional<MCFixupKind> getFixupKind(StringRef Name) const;
87 
88   /// Get information on a fixup kind.
89   virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
90 
91   /// Hook to check if a relocation is needed for some target specific reason.
shouldForceRelocation(const MCAssembler & Asm,const MCFixup & Fixup,const MCValue & Target)92   virtual bool shouldForceRelocation(const MCAssembler &Asm,
93                                      const MCFixup &Fixup,
94                                      const MCValue &Target) {
95     return false;
96   }
97 
98   /// Hook to check if extra nop bytes must be inserted for alignment directive.
99   /// For some targets this may be necessary in order to support linker
100   /// relaxation. The number of bytes to insert are returned in Size.
shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment & AF,unsigned & Size)101   virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
102                                                      unsigned &Size) {
103     return false;
104   }
105 
106   /// Hook which indicates if the target requires a fixup to be generated when
107   /// handling an align directive in an executable section
shouldInsertFixupForCodeAlign(MCAssembler & Asm,const MCAsmLayout & Layout,MCAlignFragment & AF)108   virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
109                                              const MCAsmLayout &Layout,
110                                              MCAlignFragment &AF) {
111     return false;
112   }
113 
evaluateTargetFixup(const MCAssembler & Asm,const MCAsmLayout & Layout,const MCFixup & Fixup,const MCFragment * DF,const MCValue & Target,uint64_t & Value,bool & WasForced)114   virtual bool evaluateTargetFixup(const MCAssembler &Asm,
115                                    const MCAsmLayout &Layout,
116                                    const MCFixup &Fixup, const MCFragment *DF,
117                                    const MCValue &Target, uint64_t &Value,
118                                    bool &WasForced) {
119     llvm_unreachable("Need to implement hook if target has custom fixups");
120   }
121 
122   /// Apply the \p Value for given \p Fixup into the provided data fragment, at
123   /// the offset specified by the fixup and following the fixup kind as
124   /// appropriate. Errors (such as an out of range fixup value) should be
125   /// reported via \p Ctx.
126   /// The  \p STI is present only for fragments of type MCRelaxableFragment and
127   /// MCDataFragment with hasInstructions() == true.
128   virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
129                           const MCValue &Target, MutableArrayRef<char> Data,
130                           uint64_t Value, bool IsResolved,
131                           const MCSubtargetInfo *STI) const = 0;
132 
133   /// @}
134 
135   /// \name Target Relaxation Interfaces
136   /// @{
137 
138   /// Check whether the given instruction may need relaxation.
139   ///
140   /// \param Inst - The instruction to test.
141   /// \param STI - The MCSubtargetInfo in effect when the instruction was
142   /// encoded.
mayNeedRelaxation(const MCInst & Inst,const MCSubtargetInfo & STI)143   virtual bool mayNeedRelaxation(const MCInst &Inst,
144                                  const MCSubtargetInfo &STI) const {
145     return false;
146   }
147 
148   /// Target specific predicate for whether a given fixup requires the
149   /// associated instruction to be relaxed.
150   virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
151                                             uint64_t Value,
152                                             const MCRelaxableFragment *DF,
153                                             const MCAsmLayout &Layout,
154                                             const bool WasForced) const;
155 
156   /// Simple predicate for targets where !Resolved implies requiring relaxation
157   virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
158                                     const MCRelaxableFragment *DF,
159                                     const MCAsmLayout &Layout) const = 0;
160 
161   /// Relax the instruction in the given fragment to the next wider instruction.
162   ///
163   /// \param [out] Inst The instruction to relax, which is also the relaxed
164   /// instruction.
165   /// \param STI the subtarget information for the associated instruction.
relaxInstruction(MCInst & Inst,const MCSubtargetInfo & STI)166   virtual void relaxInstruction(MCInst &Inst,
167                                 const MCSubtargetInfo &STI) const {};
168 
relaxDwarfLineAddr(MCDwarfLineAddrFragment & DF,MCAsmLayout & Layout,bool & WasRelaxed)169   virtual bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
170                                   MCAsmLayout &Layout, bool &WasRelaxed) const {
171     return false;
172   }
173 
relaxDwarfCFA(MCDwarfCallFrameFragment & DF,MCAsmLayout & Layout,bool & WasRelaxed)174   virtual bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout,
175                              bool &WasRelaxed) const {
176     return false;
177   }
178 
179   /// @}
180 
181   /// Returns the minimum size of a nop in bytes on this target. The assembler
182   /// will use this to emit excess padding in situations where the padding
183   /// required for simple alignment would be less than the minimum nop size.
184   ///
getMinimumNopSize()185   virtual unsigned getMinimumNopSize() const { return 1; }
186 
187   /// Returns the maximum size of a nop in bytes on this target.
188   ///
getMaximumNopSize(const MCSubtargetInfo & STI)189   virtual unsigned getMaximumNopSize(const MCSubtargetInfo &STI) const {
190     return 0;
191   }
192 
193   /// Write an (optimal) nop sequence of Count bytes to the given output. If the
194   /// target cannot generate such a sequence, it should return an error.
195   ///
196   /// \return - True on success.
197   virtual bool writeNopData(raw_ostream &OS, uint64_t Count,
198                             const MCSubtargetInfo *STI) const = 0;
199 
200   /// Give backend an opportunity to finish layout after relaxation
finishLayout(MCAssembler const & Asm,MCAsmLayout & Layout)201   virtual void finishLayout(MCAssembler const &Asm,
202                             MCAsmLayout &Layout) const {}
203 
204   /// Handle any target-specific assembler flags. By default, do nothing.
handleAssemblerFlag(MCAssemblerFlag Flag)205   virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}
206 
207   /// Generate the compact unwind encoding for the CFI instructions.
208   virtual uint32_t
generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>)209       generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const {
210     return 0;
211   }
212 
213   /// Check whether a given symbol has been flagged with MICROMIPS flag.
isMicroMips(const MCSymbol * Sym)214   virtual bool isMicroMips(const MCSymbol *Sym) const {
215     return false;
216   }
217 };
218 
219 } // end namespace llvm
220 
221 #endif // LLVM_MC_MCASMBACKEND_H
222