//===-- VEMCCodeEmitter.cpp - Convert VE code to machine code -------------===// // // 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 // //===----------------------------------------------------------------------===// // // This file implements the VEMCCodeEmitter class. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/VEFixupKinds.h" #include "VE.h" #include "VEMCExpr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace llvm; #define DEBUG_TYPE "mccodeemitter" STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); namespace { class VEMCCodeEmitter : public MCCodeEmitter { const MCInstrInfo &MCII; MCContext &Ctx; public: VEMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) : MCII(mcii), Ctx(ctx) {} VEMCCodeEmitter(const VEMCCodeEmitter &) = delete; VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete; ~VEMCCodeEmitter() override = default; void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override; // getBinaryCodeForInstr - TableGen'erated function for getting the // binary encoding for an instruction. uint64_t getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; private: FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; void verifyInstructionPredicates(const MCInst &MI, const FeatureBitset &AvailableFeatures) const; }; } // end anonymous namespace void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { verifyInstructionPredicates(MI, computeAvailableFeatures(STI.getFeatureBits())); uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); support::endian::write(OS, Bits, support::little); ++MCNumEmitted; // Keep track of the # of mi's emitted. } unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) return MO.getImm(); assert(MO.isExpr()); const MCExpr *Expr = MO.getExpr(); if (const VEMCExpr *SExpr = dyn_cast(Expr)) { MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); Fixups.push_back(MCFixup::create(0, Expr, Kind)); return 0; } int64_t Res; if (Expr->evaluateAsAbsolute(Res)) return Res; llvm_unreachable("Unhandled expression!"); return 0; } uint64_t VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpNo); if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); Fixups.push_back( MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_pc_lo32)); return 0; } uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) return VECondCodeToVal( static_cast(getMachineOpValue(MI, MO, Fixups, STI))); return 0; } uint64_t VEMCCodeEmitter::getRDOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) return VERDToVal(static_cast( getMachineOpValue(MI, MO, Fixups, STI))); return 0; } #define ENABLE_INSTR_PREDICATE_VERIFIER #include "VEGenMCCodeEmitter.inc" MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx) { return new VEMCCodeEmitter(MCII, Ctx); }