//===-- 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 "VEMCAsmInfo.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 #include using namespace llvm; #define DEBUG_TYPE "mccodeemitter" STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); namespace { class VEMCCodeEmitter : public MCCodeEmitter { MCContext &Ctx; public: VEMCCodeEmitter(const MCInstrInfo &, MCContext &ctx) : Ctx(ctx) {} VEMCCodeEmitter(const VEMCCodeEmitter &) = delete; VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete; ~VEMCCodeEmitter() override = default; void encodeInstruction(const MCInst &MI, SmallVectorImpl &CB, 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; }; } // end anonymous namespace static void addFixup(SmallVectorImpl &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind) { bool PCRel = false; switch (Kind) { case VE::fixup_ve_srel32: case VE::fixup_ve_pc_hi32: case VE::fixup_ve_pc_lo32: PCRel = true; } Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel)); } void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, SmallVectorImpl &CB, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); support::endian::write(CB, Bits, llvm::endianness::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 static_cast(MO.getImm()); assert(MO.isExpr()); const MCExpr *Expr = MO.getExpr(); if (const auto *SExpr = dyn_cast(Expr)) { auto Kind = VE::getFixupKind(SExpr->getSpecifier()); addFixup(Fixups, 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); addFixup(Fixups, 0, MO.getExpr(), VE::fixup_ve_srel32); 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; } #include "VEGenMCCodeEmitter.inc" MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx) { return new VEMCCodeEmitter(MCII, Ctx); }