Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
35294 views
//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the LoongArchMCCodeEmitter class.9//10//===----------------------------------------------------------------------===//1112#include "LoongArchFixupKinds.h"13#include "MCTargetDesc/LoongArchBaseInfo.h"14#include "MCTargetDesc/LoongArchMCExpr.h"15#include "MCTargetDesc/LoongArchMCTargetDesc.h"16#include "llvm/MC/MCCodeEmitter.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCInstBuilder.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCRegisterInfo.h"21#include "llvm/MC/MCSubtargetInfo.h"22#include "llvm/Support/Casting.h"23#include "llvm/Support/EndianStream.h"2425using namespace llvm;2627#define DEBUG_TYPE "mccodeemitter"2829namespace {30class LoongArchMCCodeEmitter : public MCCodeEmitter {31LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;32void operator=(const LoongArchMCCodeEmitter &) = delete;33MCContext &Ctx;34MCInstrInfo const &MCII;3536public:37LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)38: Ctx(ctx), MCII(MCII) {}3940~LoongArchMCCodeEmitter() override {}4142void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,43SmallVectorImpl<MCFixup> &Fixups,44const MCSubtargetInfo &STI) const override;4546template <unsigned Opc>47void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB,48SmallVectorImpl<MCFixup> &Fixups,49const MCSubtargetInfo &STI) const;5051void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,52SmallVectorImpl<MCFixup> &Fixups,53const MCSubtargetInfo &STI) const;5455/// TableGen'erated function for getting the binary encoding for an56/// instruction.57uint64_t getBinaryCodeForInstr(const MCInst &MI,58SmallVectorImpl<MCFixup> &Fixups,59const MCSubtargetInfo &STI) const;6061/// Return binary encoding of operand. If the machine operand requires62/// relocation, record the relocation and return zero.63unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,64SmallVectorImpl<MCFixup> &Fixups,65const MCSubtargetInfo &STI) const;6667/// Return binary encoding of an immediate operand specified by OpNo.68/// The value returned is the value of the immediate minus 1.69/// Note that this function is dedicated to specific immediate types,70/// e.g. uimm2_plus1.71unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo,72SmallVectorImpl<MCFixup> &Fixups,73const MCSubtargetInfo &STI) const;7475/// Return binary encoding of an immediate operand specified by OpNo.76/// The value returned is the value of the immediate shifted right77// arithmetically by N.78/// Note that this function is dedicated to specific immediate types,79/// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2.80template <unsigned N>81unsigned getImmOpValueAsr(const MCInst &MI, unsigned OpNo,82SmallVectorImpl<MCFixup> &Fixups,83const MCSubtargetInfo &STI) const {84const MCOperand &MO = MI.getOperand(OpNo);85if (MO.isImm()) {86unsigned Res = MI.getOperand(OpNo).getImm();87assert((Res & ((1U << N) - 1U)) == 0 && "lowest N bits are non-zero");88return Res >> N;89}90return getExprOpValue(MI, MO, Fixups, STI);91}9293unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO,94SmallVectorImpl<MCFixup> &Fixups,95const MCSubtargetInfo &STI) const;96};97} // end namespace9899unsigned100LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,101SmallVectorImpl<MCFixup> &Fixups,102const MCSubtargetInfo &STI) const {103104if (MO.isReg())105return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());106107if (MO.isImm())108return static_cast<unsigned>(MO.getImm());109110// MO must be an Expr.111assert(MO.isExpr());112return getExprOpValue(MI, MO, Fixups, STI);113}114115unsigned116LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,117SmallVectorImpl<MCFixup> &Fixups,118const MCSubtargetInfo &STI) const {119return MI.getOperand(OpNo).getImm() - 1;120}121122unsigned123LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,124SmallVectorImpl<MCFixup> &Fixups,125const MCSubtargetInfo &STI) const {126assert(MO.isExpr() && "getExprOpValue expects only expressions");127bool RelaxCandidate = false;128bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);129const MCExpr *Expr = MO.getExpr();130MCExpr::ExprKind Kind = Expr->getKind();131LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid;132if (Kind == MCExpr::Target) {133const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr);134135RelaxCandidate = LAExpr->getRelaxHint();136switch (LAExpr->getKind()) {137case LoongArchMCExpr::VK_LoongArch_None:138case LoongArchMCExpr::VK_LoongArch_Invalid:139llvm_unreachable("Unhandled fixup kind!");140case LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R:141llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an "142"instruction operand");143case LoongArchMCExpr::VK_LoongArch_B16:144FixupKind = LoongArch::fixup_loongarch_b16;145break;146case LoongArchMCExpr::VK_LoongArch_B21:147FixupKind = LoongArch::fixup_loongarch_b21;148break;149case LoongArchMCExpr::VK_LoongArch_B26:150case LoongArchMCExpr::VK_LoongArch_CALL:151case LoongArchMCExpr::VK_LoongArch_CALL_PLT:152FixupKind = LoongArch::fixup_loongarch_b26;153break;154case LoongArchMCExpr::VK_LoongArch_ABS_HI20:155FixupKind = LoongArch::fixup_loongarch_abs_hi20;156break;157case LoongArchMCExpr::VK_LoongArch_ABS_LO12:158FixupKind = LoongArch::fixup_loongarch_abs_lo12;159break;160case LoongArchMCExpr::VK_LoongArch_ABS64_LO20:161FixupKind = LoongArch::fixup_loongarch_abs64_lo20;162break;163case LoongArchMCExpr::VK_LoongArch_ABS64_HI12:164FixupKind = LoongArch::fixup_loongarch_abs64_hi12;165break;166case LoongArchMCExpr::VK_LoongArch_PCALA_HI20:167FixupKind = LoongArch::fixup_loongarch_pcala_hi20;168break;169case LoongArchMCExpr::VK_LoongArch_PCALA_LO12:170FixupKind = LoongArch::fixup_loongarch_pcala_lo12;171break;172case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20:173FixupKind = LoongArch::fixup_loongarch_pcala64_lo20;174break;175case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12:176FixupKind = LoongArch::fixup_loongarch_pcala64_hi12;177break;178case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20:179FixupKind = LoongArch::fixup_loongarch_got_pc_hi20;180break;181case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12:182FixupKind = LoongArch::fixup_loongarch_got_pc_lo12;183break;184case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20:185FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20;186break;187case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12:188FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12;189break;190case LoongArchMCExpr::VK_LoongArch_GOT_HI20:191FixupKind = LoongArch::fixup_loongarch_got_hi20;192break;193case LoongArchMCExpr::VK_LoongArch_GOT_LO12:194FixupKind = LoongArch::fixup_loongarch_got_lo12;195break;196case LoongArchMCExpr::VK_LoongArch_GOT64_LO20:197FixupKind = LoongArch::fixup_loongarch_got64_lo20;198break;199case LoongArchMCExpr::VK_LoongArch_GOT64_HI12:200FixupKind = LoongArch::fixup_loongarch_got64_hi12;201break;202case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20:203FixupKind = LoongArch::fixup_loongarch_tls_le_hi20;204break;205case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12:206FixupKind = LoongArch::fixup_loongarch_tls_le_lo12;207break;208case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20:209FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20;210break;211case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12:212FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12;213break;214case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20:215FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20;216break;217case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12:218FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12;219break;220case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20:221FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20;222break;223case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12:224FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12;225break;226case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20:227FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20;228break;229case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12:230FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12;231break;232case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20:233FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20;234break;235case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12:236FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12;237break;238case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20:239FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20;240break;241case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20:242FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20;243break;244case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20:245FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20;246break;247case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20:248FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20;249break;250case LoongArchMCExpr::VK_LoongArch_CALL36:251FixupKind = LoongArch::fixup_loongarch_call36;252break;253case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20:254FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_hi20;255break;256case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12:257FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_lo12;258break;259case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20:260FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_lo20;261break;262case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12:263FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_hi12;264break;265case LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20:266FixupKind = LoongArch::fixup_loongarch_tls_desc_hi20;267break;268case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12:269FixupKind = LoongArch::fixup_loongarch_tls_desc_lo12;270break;271case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20:272FixupKind = LoongArch::fixup_loongarch_tls_desc64_lo20;273break;274case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12:275FixupKind = LoongArch::fixup_loongarch_tls_desc64_hi12;276break;277case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD:278FixupKind = LoongArch::fixup_loongarch_tls_desc_ld;279break;280case LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL:281FixupKind = LoongArch::fixup_loongarch_tls_desc_call;282break;283case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R:284FixupKind = LoongArch::fixup_loongarch_tls_le_hi20_r;285break;286case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R:287FixupKind = LoongArch::fixup_loongarch_tls_le_lo12_r;288break;289case LoongArchMCExpr::VK_LoongArch_PCREL20_S2:290FixupKind = LoongArch::fixup_loongarch_pcrel20_s2;291break;292case LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2:293FixupKind = LoongArch::fixup_loongarch_tls_ld_pcrel20_s2;294break;295case LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2:296FixupKind = LoongArch::fixup_loongarch_tls_gd_pcrel20_s2;297break;298case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2:299FixupKind = LoongArch::fixup_loongarch_tls_desc_pcrel20_s2;300break;301}302} else if (Kind == MCExpr::SymbolRef &&303cast<MCSymbolRefExpr>(Expr)->getKind() ==304MCSymbolRefExpr::VK_None) {305switch (MI.getOpcode()) {306default:307break;308case LoongArch::BEQ:309case LoongArch::BNE:310case LoongArch::BLT:311case LoongArch::BGE:312case LoongArch::BLTU:313case LoongArch::BGEU:314FixupKind = LoongArch::fixup_loongarch_b16;315break;316case LoongArch::BEQZ:317case LoongArch::BNEZ:318case LoongArch::BCEQZ:319case LoongArch::BCNEZ:320FixupKind = LoongArch::fixup_loongarch_b21;321break;322case LoongArch::B:323case LoongArch::BL:324FixupKind = LoongArch::fixup_loongarch_b26;325break;326}327}328329assert(FixupKind != LoongArch::fixup_loongarch_invalid &&330"Unhandled expression!");331332Fixups.push_back(333MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));334335// Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax336// hint.337if (EnableRelax && RelaxCandidate) {338const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);339Fixups.push_back(MCFixup::create(3400, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc()));341}342343return 0;344}345346template <unsigned Opc>347void LoongArchMCCodeEmitter::expandToVectorLDI(348const MCInst &MI, SmallVectorImpl<char> &CB,349SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {350int64_t Imm = MI.getOperand(1).getImm() & 0x3FF;351switch (MI.getOpcode()) {352case LoongArch::PseudoVREPLI_B:353case LoongArch::PseudoXVREPLI_B:354break;355case LoongArch::PseudoVREPLI_H:356case LoongArch::PseudoXVREPLI_H:357Imm |= 0x400;358break;359case LoongArch::PseudoVREPLI_W:360case LoongArch::PseudoXVREPLI_W:361Imm |= 0x800;362break;363case LoongArch::PseudoVREPLI_D:364case LoongArch::PseudoXVREPLI_D:365Imm |= 0xC00;366break;367}368MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm);369uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);370support::endian::write(CB, Binary, llvm::endianness::little);371}372373void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,374SmallVectorImpl<char> &CB,375SmallVectorImpl<MCFixup> &Fixups,376const MCSubtargetInfo &STI) const {377MCOperand Rd = MI.getOperand(0);378MCOperand Rj = MI.getOperand(1);379MCOperand Rk = MI.getOperand(2);380MCOperand Symbol = MI.getOperand(3);381assert(Symbol.isExpr() &&382"Expected expression as third input to TP-relative add");383384const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr());385assert(Expr &&386Expr->getKind() == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R &&387"Expected %le_add_r relocation on TP-relative symbol");388389// Emit the correct %le_add_r relocation for the symbol.390// TODO: Emit R_LARCH_RELAX for %le_add_r where the relax feature is enabled.391Fixups.push_back(MCFixup::create(3920, Expr, MCFixupKind(LoongArch::fixup_loongarch_tls_le_add_r),393MI.getLoc()));394395// Emit a normal ADD instruction with the given operands.396unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D397? LoongArch::ADD_D398: LoongArch::ADD_W;399MCInst TmpInst =400MCInstBuilder(ADD).addOperand(Rd).addOperand(Rj).addOperand(Rk);401uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);402support::endian::write(CB, Binary, llvm::endianness::little);403}404405void LoongArchMCCodeEmitter::encodeInstruction(406const MCInst &MI, SmallVectorImpl<char> &CB,407SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {408const MCInstrDesc &Desc = MCII.get(MI.getOpcode());409// Get byte count of instruction.410unsigned Size = Desc.getSize();411412switch (MI.getOpcode()) {413default:414break;415case LoongArch::PseudoVREPLI_B:416case LoongArch::PseudoVREPLI_H:417case LoongArch::PseudoVREPLI_W:418case LoongArch::PseudoVREPLI_D:419return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI);420case LoongArch::PseudoXVREPLI_B:421case LoongArch::PseudoXVREPLI_H:422case LoongArch::PseudoXVREPLI_W:423case LoongArch::PseudoXVREPLI_D:424return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI);425case LoongArch::PseudoAddTPRel_W:426case LoongArch::PseudoAddTPRel_D:427return expandAddTPRel(MI, CB, Fixups, STI);428}429430switch (Size) {431default:432llvm_unreachable("Unhandled encodeInstruction length!");433case 4: {434uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);435support::endian::write(CB, Bits, llvm::endianness::little);436break;437}438}439}440441MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,442MCContext &Ctx) {443return new LoongArchMCCodeEmitter(Ctx, MCII);444}445446#include "LoongArchGenMCCodeEmitter.inc"447448449