llvm/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp

//===-- X86AsmBackend.cpp - X86 Assembler Backend -------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/X86BaseInfo.h"
#include "MCTargetDesc/X86EncodingOptimization.h"
#include "MCTargetDesc/X86FixupKinds.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCMachObjectWriter.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

usingnamespacellvm;

namespace {
/// A wrapper for holding a mask of the values from X86::AlignBranchBoundaryKind
class X86AlignBranchKind {};

X86AlignBranchKind X86AlignBranchKindLoc;

cl::opt<unsigned> X86AlignBranchBoundary(
    "x86-align-branch-boundary", cl::init(0),
    cl::desc(
        "Control how the assembler should align branches with NOP. If the "
        "boundary's size is not 0, it should be a power of 2 and no less "
        "than 32. Branches will be aligned to prevent from being across or "
        "against the boundary of specified size. The default value 0 does not "
        "align branches."));

cl::opt<X86AlignBranchKind, true, cl::parser<std::string>> X86AlignBranch(
    "x86-align-branch",
    cl::desc(
        "Specify types of branches to align (plus separated list of types):"
             "\njcc      indicates conditional jumps"
             "\nfused    indicates fused conditional jumps"
             "\njmp      indicates direct unconditional jumps"
             "\ncall     indicates direct and indirect calls"
             "\nret      indicates rets"
             "\nindirect indicates indirect unconditional jumps"),
    cl::location(X86AlignBranchKindLoc));

cl::opt<bool> X86AlignBranchWithin32BBoundaries(
    "x86-branches-within-32B-boundaries", cl::init(false),
    cl::desc(
        "Align selected instructions to mitigate negative performance impact "
        "of Intel's micro code update for errata skx102.  May break "
        "assumptions about labels corresponding to particular instructions, "
        "and should be used with caution."));

cl::opt<unsigned> X86PadMaxPrefixSize(
    "x86-pad-max-prefix-size", cl::init(0),
    cl::desc("Maximum number of prefixes to use for padding"));

cl::opt<bool> X86PadForAlign(
    "x86-pad-for-align", cl::init(false), cl::Hidden,
    cl::desc("Pad previous instructions to implement align directives"));

cl::opt<bool> X86PadForBranchAlign(
    "x86-pad-for-branch-align", cl::init(true), cl::Hidden,
    cl::desc("Pad previous instructions to implement branch alignment"));

class X86AsmBackend : public MCAsmBackend {};
} // end anonymous namespace

static bool isRelaxableBranch(unsigned Opcode) {}

static unsigned getRelaxedOpcodeBranch(unsigned Opcode,
                                       bool Is16BitMode = false) {}

static unsigned getRelaxedOpcode(const MCInst &MI, bool Is16BitMode) {}

static X86::CondCode getCondFromBranch(const MCInst &MI,
                                       const MCInstrInfo &MCII) {}

static X86::SecondMacroFusionInstKind
classifySecondInstInMacroFusion(const MCInst &MI, const MCInstrInfo &MCII) {}

/// Check if the instruction uses RIP relative addressing.
static bool isRIPRelative(const MCInst &MI, const MCInstrInfo &MCII) {}

/// Check if the instruction is a prefix.
static bool isPrefix(unsigned Opcode, const MCInstrInfo &MCII) {}

/// Check if the instruction is valid as the first instruction in macro fusion.
static bool isFirstMacroFusibleInst(const MCInst &Inst,
                                    const MCInstrInfo &MCII) {}

/// X86 can reduce the bytes of NOP by padding instructions with prefixes to
/// get a better peformance in some cases. Here, we determine which prefix is
/// the most suitable.
///
/// If the instruction has a segment override prefix, use the existing one.
/// If the target is 64-bit, use the CS.
/// If the target is 32-bit,
///   - If the instruction has a ESP/EBP base register, use SS.
///   - Otherwise use DS.
uint8_t X86AsmBackend::determinePaddingPrefix(const MCInst &Inst) const {}

/// Check if the two instructions will be macro-fused on the target cpu.
bool X86AsmBackend::isMacroFused(const MCInst &Cmp, const MCInst &Jcc) const {}

/// Check if the instruction has a variant symbol operand.
static bool hasVariantSymbol(const MCInst &MI) {}

bool X86AsmBackend::allowAutoPadding() const {}

bool X86AsmBackend::allowEnhancedRelaxation() const {}

/// X86 has certain instructions which enable interrupts exactly one
/// instruction *after* the instruction which stores to SS.  Return true if the
/// given instruction may have such an interrupt delay slot.
static bool mayHaveInterruptDelaySlot(unsigned InstOpcode) {}

/// Check if the instruction to be emitted is right after any data.
static bool
isRightAfterData(MCFragment *CurrentFragment,
                 const std::pair<MCFragment *, size_t> &PrevInstPosition) {}

/// \returns the fragment size if it has instructions, otherwise returns 0.
static size_t getSizeForInstFragment(const MCFragment *F) {}

/// Return true if we can insert NOP or prefixes automatically before the
/// the instruction to be emitted.
bool X86AsmBackend::canPadInst(const MCInst &Inst, MCObjectStreamer &OS) const {}

bool X86AsmBackend::canPadBranches(MCObjectStreamer &OS) const {}

/// Check if the instruction operand needs to be aligned.
bool X86AsmBackend::needAlign(const MCInst &Inst) const {}

/// Insert BoundaryAlignFragment before instructions to align branches.
void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
                                         const MCInst &Inst, const MCSubtargetInfo &STI) {}

/// Set the last fragment to be aligned for the BoundaryAlignFragment.
void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS,
                                       const MCInst &Inst) {}

std::optional<MCFixupKind> X86AsmBackend::getFixupKind(StringRef Name) const {}

const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {}

bool X86AsmBackend::shouldForceRelocation(const MCAssembler &,
                                          const MCFixup &Fixup, const MCValue &,
                                          const MCSubtargetInfo *STI) {}

static unsigned getFixupKindSize(unsigned Kind) {}

void X86AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
                               const MCValue &Target,
                               MutableArrayRef<char> Data,
                               uint64_t Value, bool IsResolved,
                               const MCSubtargetInfo *STI) const {}

bool X86AsmBackend::mayNeedRelaxation(const MCInst &MI,
                                      const MCSubtargetInfo &STI) const {}

bool X86AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
                                         uint64_t Value) const {}

// FIXME: Can tblgen help at all here to verify there aren't other instructions
// we can relax?
void X86AsmBackend::relaxInstruction(MCInst &Inst,
                                     const MCSubtargetInfo &STI) const {}

bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF,
                                            MCCodeEmitter &Emitter,
                                            unsigned &RemainingSize) const {}

bool X86AsmBackend::padInstructionViaRelaxation(MCRelaxableFragment &RF,
                                                MCCodeEmitter &Emitter,
                                                unsigned &RemainingSize) const {}

bool X86AsmBackend::padInstructionEncoding(MCRelaxableFragment &RF,
                                           MCCodeEmitter &Emitter,
                                           unsigned &RemainingSize) const {}

void X86AsmBackend::finishLayout(MCAssembler const &Asm) const {}

unsigned X86AsmBackend::getMaximumNopSize(const MCSubtargetInfo &STI) const {}

/// Write a sequence of optimal nops to the output, covering \p Count
/// bytes.
/// \return - true on success, false on failure
bool X86AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
                                 const MCSubtargetInfo *STI) const {}

/* *** */

namespace {

class ELFX86AsmBackend : public X86AsmBackend {};

class ELFX86_32AsmBackend : public ELFX86AsmBackend {};

class ELFX86_X32AsmBackend : public ELFX86AsmBackend {};

class ELFX86_IAMCUAsmBackend : public ELFX86AsmBackend {};

class ELFX86_64AsmBackend : public ELFX86AsmBackend {};

class WindowsX86AsmBackend : public X86AsmBackend {};

namespace CU {

  /// Compact unwind encoding values.
  enum CompactUnwindEncodings {};

} // namespace CU

class DarwinX86AsmBackend : public X86AsmBackend {};

} // end anonymous namespace

MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T,
                                           const MCSubtargetInfo &STI,
                                           const MCRegisterInfo &MRI,
                                           const MCTargetOptions &Options) {}

MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
                                           const MCSubtargetInfo &STI,
                                           const MCRegisterInfo &MRI,
                                           const MCTargetOptions &Options) {}

namespace {
class X86ELFStreamer : public MCELFStreamer {};
} // end anonymous namespace

void X86_MC::emitInstruction(MCObjectStreamer &S, const MCInst &Inst,
                             const MCSubtargetInfo &STI) {}

void X86ELFStreamer::emitInstruction(const MCInst &Inst,
                                     const MCSubtargetInfo &STI) {}

MCStreamer *llvm::createX86ELFStreamer(const Triple &T, MCContext &Context,
                                       std::unique_ptr<MCAsmBackend> &&MAB,
                                       std::unique_ptr<MCObjectWriter> &&MOW,
                                       std::unique_ptr<MCCodeEmitter> &&MCE) {}