//===-- M68kMCInstLower.cpp - M68k MachineInstr to MCInst -------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// /// /// \file /// This file contains code to lower M68k MachineInstrs to their /// corresponding MCInst records. /// //===----------------------------------------------------------------------===// #include "M68kMCInstLower.h" #include "M68kAsmPrinter.h" #include "M68kInstrInfo.h" #include "MCTargetDesc/M68kBaseInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/IR/Mangler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" using namespace llvm; #define DEBUG_TYPE "m68k-mc-inst-lower" M68kMCInstLower::M68kMCInstLower(MachineFunction &MF, M68kAsmPrinter &AP) : Ctx(MF.getContext()), MF(MF), TM(MF.getTarget()), MAI(*TM.getMCAsmInfo()), AsmPrinter(AP) {} MCSymbol * M68kMCInstLower::GetSymbolFromOperand(const MachineOperand &MO) const { assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) && "Isn't a symbol reference"); const auto &TT = TM.getTargetTriple(); if (MO.isGlobal() && TT.isOSBinFormatELF()) return AsmPrinter.getSymbolPreferLocal(*MO.getGlobal()); const DataLayout &DL = MF.getDataLayout(); MCSymbol *Sym = nullptr; SmallString<128> Name; StringRef Suffix; if (!Suffix.empty()) Name += DL.getPrivateGlobalPrefix(); if (MO.isGlobal()) { const GlobalValue *GV = MO.getGlobal(); AsmPrinter.getNameWithPrefix(Name, GV); } else if (MO.isSymbol()) { Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); } else if (MO.isMBB()) { assert(Suffix.empty()); Sym = MO.getMBB()->getSymbol(); } Name += Suffix; if (!Sym) Sym = Ctx.getOrCreateSymbol(Name); return Sym; } MCOperand M68kMCInstLower::LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const { // FIXME We would like an efficient form for this, so we don't have to do a // lot of extra uniquing. This fixme is originally from X86 const MCExpr *Expr = nullptr; MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; switch (MO.getTargetFlags()) { default: llvm_unreachable("Unknown target flag on GV operand"); case M68kII::MO_NO_FLAG: case M68kII::MO_ABSOLUTE_ADDRESS: case M68kII::MO_PC_RELATIVE_ADDRESS: break; case M68kII::MO_GOTPCREL: RefKind = MCSymbolRefExpr::VK_GOTPCREL; break; case M68kII::MO_GOT: RefKind = MCSymbolRefExpr::VK_GOT; break; case M68kII::MO_GOTOFF: RefKind = MCSymbolRefExpr::VK_GOTOFF; break; case M68kII::MO_PLT: RefKind = MCSymbolRefExpr::VK_PLT; break; case M68kII::MO_TLSGD: RefKind = MCSymbolRefExpr::VK_TLSGD; break; case M68kII::MO_TLSLD: RefKind = MCSymbolRefExpr::VK_TLSLD; break; case M68kII::MO_TLSLDM: RefKind = MCSymbolRefExpr::VK_TLSLDM; break; case M68kII::MO_TLSIE: RefKind = MCSymbolRefExpr::VK_GOTTPOFF; break; case M68kII::MO_TLSLE: RefKind = MCSymbolRefExpr::VK_TPOFF; break; } if (!Expr) { Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); } if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) { Expr = MCBinaryExpr::createAdd( Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); } return MCOperand::createExpr(Expr); } std::optional M68kMCInstLower::LowerOperand(const MachineInstr *MI, const MachineOperand &MO) const { switch (MO.getType()) { default: llvm_unreachable("unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) return std::nullopt; return MCOperand::createReg(MO.getReg()); case MachineOperand::MO_Immediate: return MCOperand::createImm(MO.getImm()); case MachineOperand::MO_MachineBasicBlock: case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ExternalSymbol: return LowerSymbolOperand(MO, GetSymbolFromOperand(MO)); case MachineOperand::MO_MCSymbol: return LowerSymbolOperand(MO, MO.getMCSymbol()); case MachineOperand::MO_JumpTableIndex: return LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex())); case MachineOperand::MO_ConstantPoolIndex: return LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex())); case MachineOperand::MO_BlockAddress: return LowerSymbolOperand( MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress())); case MachineOperand::MO_RegisterMask: // Ignore call clobbers. return std::nullopt; } } void M68kMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { unsigned Opcode = MI->getOpcode(); OutMI.setOpcode(Opcode); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); std::optional MCOp = LowerOperand(MI, MO); if (MCOp.has_value() && MCOp.value().isValid()) OutMI.addOperand(MCOp.value()); } // TAILJMPj, TAILJMPq - Lower to the correct jump instructions. if (Opcode == M68k::TAILJMPj || Opcode == M68k::TAILJMPq) { assert(OutMI.getNumOperands() == 1 && "Unexpected number of operands"); switch (Opcode) { case M68k::TAILJMPj: Opcode = M68k::JMP32j; break; case M68k::TAILJMPq: Opcode = M68k::BRA8; break; } OutMI.setOpcode(Opcode); } }