Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// | //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// | ||||
// | // | ||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
// See https://llvm.org/LICENSE.txt for license information. | // See https://llvm.org/LICENSE.txt for license information. | ||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// | // | ||||
// This file implements the LoongArchMCCodeEmitter class. | // This file implements the LoongArchMCCodeEmitter class. | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#include "LoongArchFixupKinds.h" | |||||
#include "MCTargetDesc/LoongArchBaseInfo.h" | #include "MCTargetDesc/LoongArchBaseInfo.h" | ||||
#include "MCTargetDesc/LoongArchMCExpr.h" | |||||
#include "MCTargetDesc/LoongArchMCTargetDesc.h" | #include "MCTargetDesc/LoongArchMCTargetDesc.h" | ||||
#include "llvm/MC/MCCodeEmitter.h" | #include "llvm/MC/MCCodeEmitter.h" | ||||
#include "llvm/MC/MCContext.h" | #include "llvm/MC/MCContext.h" | ||||
#include "llvm/MC/MCInstBuilder.h" | #include "llvm/MC/MCInstBuilder.h" | ||||
#include "llvm/MC/MCInstrInfo.h" | #include "llvm/MC/MCInstrInfo.h" | ||||
#include "llvm/MC/MCRegisterInfo.h" | #include "llvm/MC/MCRegisterInfo.h" | ||||
#include "llvm/Support/Casting.h" | |||||
#include "llvm/Support/EndianStream.h" | #include "llvm/Support/EndianStream.h" | ||||
using namespace llvm; | using namespace llvm; | ||||
#define DEBUG_TYPE "mccodeemitter" | #define DEBUG_TYPE "mccodeemitter" | ||||
namespace { | namespace { | ||||
class LoongArchMCCodeEmitter : public MCCodeEmitter { | class LoongArchMCCodeEmitter : public MCCodeEmitter { | ||||
LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; | LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; | ||||
void operator=(const LoongArchMCCodeEmitter &) = delete; | void operator=(const LoongArchMCCodeEmitter &) = delete; | ||||
MCContext &Ctx; | MCContext &Ctx; | ||||
MCInstrInfo const &MCII; | MCInstrInfo const &MCII; | ||||
public: | public: | ||||
LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) | LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) | ||||
: Ctx(ctx), MCII(MCII) {} | : Ctx(ctx), MCII(MCII) {} | ||||
~LoongArchMCCodeEmitter() override {} | ~LoongArchMCCodeEmitter() override {} | ||||
void encodeInstruction(const MCInst &MI, raw_ostream &OS, | void encodeInstruction(const MCInst &MI, raw_ostream &OS, | ||||
SmallVectorImpl<MCFixup> &Fixups, | SmallVectorImpl<MCFixup> &Fixups, | ||||
const MCSubtargetInfo &STI) const override; | const MCSubtargetInfo &STI) const override; | ||||
void expandFunctionCall(const MCInst &MI, raw_ostream &OS, | |||||
SmallVectorImpl<MCFixup> &Fixups, | |||||
const MCSubtargetInfo &STI) const; | |||||
/// TableGen'erated function for getting the binary encoding for an | /// TableGen'erated function for getting the binary encoding for an | ||||
/// instruction. | /// instruction. | ||||
uint64_t getBinaryCodeForInstr(const MCInst &MI, | uint64_t getBinaryCodeForInstr(const MCInst &MI, | ||||
SmallVectorImpl<MCFixup> &Fixups, | SmallVectorImpl<MCFixup> &Fixups, | ||||
const MCSubtargetInfo &STI) const; | const MCSubtargetInfo &STI) const; | ||||
/// Return binary encoding of operand. If the machine operand requires | /// Return binary encoding of operand. If the machine operand requires | ||||
/// relocation, record the relocation and return zero. | /// relocation, record the relocation and return zero. | ||||
Show All 12 Lines | public: | ||||
/// Return binary encoding of an immediate operand specified by OpNo. | /// Return binary encoding of an immediate operand specified by OpNo. | ||||
/// The value returned is the value of the immediate shifted right | /// The value returned is the value of the immediate shifted right | ||||
// arithmetically by 2. | // arithmetically by 2. | ||||
/// Note that this function is dedicated to specific immediate types, | /// Note that this function is dedicated to specific immediate types, | ||||
/// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. | /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. | ||||
unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, | unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, | ||||
SmallVectorImpl<MCFixup> &Fixups, | SmallVectorImpl<MCFixup> &Fixups, | ||||
const MCSubtargetInfo &STI) const; | const MCSubtargetInfo &STI) const; | ||||
unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO, | |||||
SmallVectorImpl<MCFixup> &Fixups, | |||||
const MCSubtargetInfo &STI) const; | |||||
}; | }; | ||||
} // end namespace | } // end namespace | ||||
unsigned | unsigned | ||||
LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, | LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, | ||||
SmallVectorImpl<MCFixup> &Fixups, | SmallVectorImpl<MCFixup> &Fixups, | ||||
const MCSubtargetInfo &STI) const { | const MCSubtargetInfo &STI) const { | ||||
if (MO.isReg()) | if (MO.isReg()) | ||||
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); | return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); | ||||
if (MO.isImm()) | if (MO.isImm()) | ||||
return static_cast<unsigned>(MO.getImm()); | return static_cast<unsigned>(MO.getImm()); | ||||
llvm_unreachable("Unhandled expression!"); | // MO must be an Expr. | ||||
assert(MO.isExpr()); | |||||
return getExprOpValue(MI, MO, Fixups, STI); | |||||
} | } | ||||
unsigned | unsigned | ||||
LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, | LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, | ||||
SmallVectorImpl<MCFixup> &Fixups, | SmallVectorImpl<MCFixup> &Fixups, | ||||
const MCSubtargetInfo &STI) const { | const MCSubtargetInfo &STI) const { | ||||
return MI.getOperand(OpNo).getImm() - 1; | return MI.getOperand(OpNo).getImm() - 1; | ||||
} | } | ||||
unsigned | unsigned | ||||
LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, | LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, | ||||
SmallVectorImpl<MCFixup> &Fixups, | SmallVectorImpl<MCFixup> &Fixups, | ||||
const MCSubtargetInfo &STI) const { | const MCSubtargetInfo &STI) const { | ||||
const MCOperand &MO = MI.getOperand(OpNo); | |||||
if (MO.isImm()) { | |||||
unsigned Res = MI.getOperand(OpNo).getImm(); | unsigned Res = MI.getOperand(OpNo).getImm(); | ||||
assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); | assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); | ||||
return Res >> 2; | return Res >> 2; | ||||
} | } | ||||
return getExprOpValue(MI, MO, Fixups, STI); | |||||
} | |||||
unsigned | |||||
LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, | |||||
SmallVectorImpl<MCFixup> &Fixups, | |||||
const MCSubtargetInfo &STI) const { | |||||
assert(MO.isExpr() && "getExprOpValue expects only expressions"); | |||||
const MCExpr *Expr = MO.getExpr(); | |||||
MCExpr::ExprKind Kind = Expr->getKind(); | |||||
LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid; | |||||
if (Kind == MCExpr::Target) { | |||||
const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr); | |||||
switch (LAExpr->getKind()) { | |||||
case LoongArchMCExpr::VK_LoongArch_None: | |||||
case LoongArchMCExpr::VK_LoongArch_Invalid: | |||||
llvm_unreachable("Unhandled fixup kind!"); | |||||
case LoongArchMCExpr::VK_LoongArch_PCREL_HI: | |||||
FixupKind = LoongArch::fixup_loongarch_pcala_hi20; | |||||
break; | |||||
case LoongArchMCExpr::VK_LoongArch_PCREL_LO: | |||||
FixupKind = LoongArch::fixup_loongarch_pcala_lo12; | |||||
break; | |||||
case LoongArchMCExpr::VK_LoongArch_CALL: | |||||
case LoongArchMCExpr::VK_LoongArch_CALL_PLT: | |||||
FixupKind = LoongArch::fixup_loongarch_b26; | |||||
break; | |||||
} | |||||
} | |||||
assert(FixupKind != LoongArch::fixup_loongarch_invalid && | |||||
"Unhandled expression!"); | |||||
Fixups.push_back( | |||||
MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); | |||||
return 0; | |||||
} | |||||
void LoongArchMCCodeEmitter::expandFunctionCall( | |||||
const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, | |||||
const MCSubtargetInfo &STI) const { | |||||
MCOperand Func = MI.getOperand(0); | |||||
MCInst TmpInst = Func.isExpr() | |||||
? MCInstBuilder(LoongArch::BL).addExpr(Func.getExpr()) | |||||
: MCInstBuilder(LoongArch::BL).addImm(Func.getImm()); | |||||
uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); | |||||
support::endian::write(OS, Binary, support::little); | |||||
} | |||||
void LoongArchMCCodeEmitter::encodeInstruction( | void LoongArchMCCodeEmitter::encodeInstruction( | ||||
const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, | const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, | ||||
const MCSubtargetInfo &STI) const { | const MCSubtargetInfo &STI) const { | ||||
const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); | const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); | ||||
// Get byte count of instruction. | // Get byte count of instruction. | ||||
unsigned Size = Desc.getSize(); | unsigned Size = Desc.getSize(); | ||||
if (MI.getOpcode() == LoongArch::PseudoCALL) | |||||
return expandFunctionCall(MI, OS, Fixups, STI); | |||||
switch (Size) { | switch (Size) { | ||||
default: | default: | ||||
llvm_unreachable("Unhandled encodeInstruction length!"); | llvm_unreachable("Unhandled encodeInstruction length!"); | ||||
case 4: { | case 4: { | ||||
uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); | uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); | ||||
support::endian::write(OS, Bits, support::little); | support::endian::write(OS, Bits, support::little); | ||||
break; | break; | ||||
} | } | ||||
Show All 9 Lines |