//===- llvm/MC/MCAsmBackend.h - MC Asm Backend ------------------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_MC_MCASMBACKEND_H
 
#define LLVM_MC_MCASMBACKEND_H
 
 
 
#include "llvm/ADT/ArrayRef.h"
 
#include "llvm/MC/MCDirectives.h"
 
#include "llvm/MC/MCFixup.h"
 
#include "llvm/Support/Endian.h"
 
#include <cstdint>
 
 
 
namespace llvm {
 
 
 
class MCAlignFragment;
 
class MCDwarfCallFrameFragment;
 
class MCDwarfLineAddrFragment;
 
class MCFragment;
 
class MCRelaxableFragment;
 
class MCSymbol;
 
class MCAsmLayout;
 
class MCAssembler;
 
class MCCFIInstruction;
 
struct MCFixupKindInfo;
 
class MCInst;
 
class MCObjectStreamer;
 
class MCObjectTargetWriter;
 
class MCObjectWriter;
 
class MCSubtargetInfo;
 
class MCValue;
 
class raw_pwrite_stream;
 
class StringRef;
 
class raw_ostream;
 
 
 
/// Generic interface to target specific assembler backends.
 
class MCAsmBackend {
 
protected: // Can only create subclasses.
 
  MCAsmBackend(support::endianness Endian);
 
 
 
public:
 
  MCAsmBackend(const MCAsmBackend &) = delete;
 
  MCAsmBackend &operator=(const MCAsmBackend &) = delete;
 
  virtual ~MCAsmBackend();
 
 
 
  const support::endianness Endian;
 
 
 
  /// Return true if this target might automatically pad instructions and thus
 
  /// need to emit padding enable/disable directives around sensative code.
 
  virtual bool allowAutoPadding() const { return false; }
 
  /// Return true if this target allows an unrelaxable instruction to be
 
  /// emitted into RelaxableFragment and then we can increase its size in a
 
  /// tricky way for optimization.
 
  virtual bool allowEnhancedRelaxation() const { return false; }
 
 
 
  /// Give the target a chance to manipulate state related to instruction
 
  /// alignment (e.g. padding for optimization), instruction relaxablility, etc.
 
  /// before and after actually emitting the instruction.
 
  virtual void emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst,
 
                                    const MCSubtargetInfo &STI) {}
 
  virtual void emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) {}
 
 
 
  /// lifetime management
 
  virtual void reset() {}
 
 
 
  /// Create a new MCObjectWriter instance for use by the assembler backend to
 
  /// emit the final object file.
 
  std::unique_ptr<MCObjectWriter>
 
  createObjectWriter(raw_pwrite_stream &OS) const;
 
 
 
  /// Create an MCObjectWriter that writes two object files: a .o file which is
 
  /// linked into the final program and a .dwo file which is used by debuggers.
 
  /// This function is only supported with ELF targets.
 
  std::unique_ptr<MCObjectWriter>
 
  createDwoObjectWriter(raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS) const;
 
 
 
  virtual std::unique_ptr<MCObjectTargetWriter>
 
  createObjectTargetWriter() const = 0;
 
 
 
  /// \name Target Fixup Interfaces
 
  /// @{
 
 
 
  /// Get the number of target specific fixup kinds.
 
  virtual unsigned getNumFixupKinds() const = 0;
 
 
 
  /// Map a relocation name used in .reloc to a fixup kind.
 
  virtual std::optional<MCFixupKind> getFixupKind(StringRef Name) const;
 
 
 
  /// Get information on a fixup kind.
 
  virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
 
 
 
  /// Hook to check if a relocation is needed for some target specific reason.
 
  virtual bool shouldForceRelocation(const MCAssembler &Asm,
 
                                     const MCFixup &Fixup,
 
                                     const MCValue &Target) {
 
    return false;
 
  }
 
 
 
  /// Hook to check if extra nop bytes must be inserted for alignment directive.
 
  /// For some targets this may be necessary in order to support linker
 
  /// relaxation. The number of bytes to insert are returned in Size.
 
  virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
 
                                                     unsigned &Size) {
 
    return false;
 
  }
 
 
 
  /// Hook which indicates if the target requires a fixup to be generated when
 
  /// handling an align directive in an executable section
 
  virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
 
                                             const MCAsmLayout &Layout,
 
                                             MCAlignFragment &AF) {
 
    return false;
 
  }
 
 
 
  virtual bool evaluateTargetFixup(const MCAssembler &Asm,
 
                                   const MCAsmLayout &Layout,
 
                                   const MCFixup &Fixup, const MCFragment *DF,
 
                                   const MCValue &Target, uint64_t &Value,
 
                                   bool &WasForced) {
 
    llvm_unreachable("Need to implement hook if target has custom fixups");
 
  }
 
 
 
  /// Apply the \p Value for given \p Fixup into the provided data fragment, at
 
  /// the offset specified by the fixup and following the fixup kind as
 
  /// appropriate. Errors (such as an out of range fixup value) should be
 
  /// reported via \p Ctx.
 
  /// The  \p STI is present only for fragments of type MCRelaxableFragment and
 
  /// MCDataFragment with hasInstructions() == true.
 
  virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
 
                          const MCValue &Target, MutableArrayRef<char> Data,
 
                          uint64_t Value, bool IsResolved,
 
                          const MCSubtargetInfo *STI) const = 0;
 
 
 
  /// @}
 
 
 
  /// \name Target Relaxation Interfaces
 
  /// @{
 
 
 
  /// Check whether the given instruction may need relaxation.
 
  ///
 
  /// \param Inst - The instruction to test.
 
  /// \param STI - The MCSubtargetInfo in effect when the instruction was
 
  /// encoded.
 
  virtual bool mayNeedRelaxation(const MCInst &Inst,
 
                                 const MCSubtargetInfo &STI) const {
 
    return false;
 
  }
 
 
 
  /// Target specific predicate for whether a given fixup requires the
 
  /// associated instruction to be relaxed.
 
  virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
 
                                            uint64_t Value,
 
                                            const MCRelaxableFragment *DF,
 
                                            const MCAsmLayout &Layout,
 
                                            const bool WasForced) const;
 
 
 
  /// Simple predicate for targets where !Resolved implies requiring relaxation
 
  virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
 
                                    const MCRelaxableFragment *DF,
 
                                    const MCAsmLayout &Layout) const = 0;
 
 
 
  /// Relax the instruction in the given fragment to the next wider instruction.
 
  ///
 
  /// \param [out] Inst The instruction to relax, which is also the relaxed
 
  /// instruction.
 
  /// \param STI the subtarget information for the associated instruction.
 
  virtual void relaxInstruction(MCInst &Inst,
 
                                const MCSubtargetInfo &STI) const {};
 
 
 
  virtual bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
 
                                  MCAsmLayout &Layout, bool &WasRelaxed) const {
 
    return false;
 
  }
 
 
 
  virtual bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout,
 
                             bool &WasRelaxed) const {
 
    return false;
 
  }
 
 
 
  /// @}
 
 
 
  /// Returns the minimum size of a nop in bytes on this target. The assembler
 
  /// will use this to emit excess padding in situations where the padding
 
  /// required for simple alignment would be less than the minimum nop size.
 
  ///
 
  virtual unsigned getMinimumNopSize() const { return 1; }
 
 
 
  /// Returns the maximum size of a nop in bytes on this target.
 
  ///
 
  virtual unsigned getMaximumNopSize(const MCSubtargetInfo &STI) const {
 
    return 0;
 
  }
 
 
 
  /// Write an (optimal) nop sequence of Count bytes to the given output. If the
 
  /// target cannot generate such a sequence, it should return an error.
 
  ///
 
  /// \return - True on success.
 
  virtual bool writeNopData(raw_ostream &OS, uint64_t Count,
 
                            const MCSubtargetInfo *STI) const = 0;
 
 
 
  /// Give backend an opportunity to finish layout after relaxation
 
  virtual void finishLayout(MCAssembler const &Asm,
 
                            MCAsmLayout &Layout) const {}
 
 
 
  /// Handle any target-specific assembler flags. By default, do nothing.
 
  virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}
 
 
 
  /// Generate the compact unwind encoding for the CFI instructions.
 
  virtual uint32_t
 
      generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const {
 
    return 0;
 
  }
 
 
 
  /// Check whether a given symbol has been flagged with MICROMIPS flag.
 
  virtual bool isMicroMips(const MCSymbol *Sym) const {
 
    return false;
 
  }
 
};
 
 
 
} // end namespace llvm
 
 
 
#endif // LLVM_MC_MCASMBACKEND_H