1167465Smp//===-- M68kMCInstLower.cpp - M68k MachineInstr to MCInst -------*- C++ -*-===// 259243Sobrien// 359243Sobrien// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 459243Sobrien// See https://llvm.org/LICENSE.txt for license information. 559243Sobrien// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 659243Sobrien// 759243Sobrien//===----------------------------------------------------------------------===// 859243Sobrien/// 959243Sobrien/// \file 1059243Sobrien/// This file contains code to lower M68k MachineInstrs to their 11100616Smp/// corresponding MCInst records. 1259243Sobrien/// 1359243Sobrien//===----------------------------------------------------------------------===// 1459243Sobrien 1559243Sobrien#include "M68kMCInstLower.h" 1659243Sobrien 1759243Sobrien#include "M68kAsmPrinter.h" 1859243Sobrien#include "M68kInstrInfo.h" 1959243Sobrien 2059243Sobrien#include "MCTargetDesc/M68kBaseInfo.h" 2159243Sobrien 2259243Sobrien#include "llvm/CodeGen/MachineFunction.h" 2359243Sobrien#include "llvm/CodeGen/MachineInstr.h" 2459243Sobrien#include "llvm/CodeGen/MachineOperand.h" 2559243Sobrien#include "llvm/IR/Mangler.h" 2659243Sobrien#include "llvm/MC/MCContext.h" 2759243Sobrien#include "llvm/MC/MCExpr.h" 2859243Sobrien#include "llvm/MC/MCInst.h" 2959243Sobrien 3059243Sobrienusing namespace llvm; 3159243Sobrien 3259243Sobrien#define DEBUG_TYPE "m68k-mc-inst-lower" 3359243Sobrien 3459243SobrienM68kMCInstLower::M68kMCInstLower(MachineFunction &MF, M68kAsmPrinter &AP) 3559243Sobrien : Ctx(MF.getContext()), MF(MF), TM(MF.getTarget()), MAI(*TM.getMCAsmInfo()), 3659243Sobrien AsmPrinter(AP) {} 3759243Sobrien 3859243SobrienMCSymbol * 3959243SobrienM68kMCInstLower::GetSymbolFromOperand(const MachineOperand &MO) const { 4059243Sobrien assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) && 4159243Sobrien "Isn't a symbol reference"); 4259243Sobrien 4359243Sobrien const auto &TT = TM.getTargetTriple(); 4459243Sobrien if (MO.isGlobal() && TT.isOSBinFormatELF()) 4559243Sobrien return AsmPrinter.getSymbolPreferLocal(*MO.getGlobal()); 4659243Sobrien 4759243Sobrien const DataLayout &DL = MF.getDataLayout(); 4859243Sobrien 4959243Sobrien MCSymbol *Sym = nullptr; 5059243Sobrien SmallString<128> Name; 5159243Sobrien StringRef Suffix; 5259243Sobrien 5359243Sobrien if (!Suffix.empty()) 5459243Sobrien Name += DL.getPrivateGlobalPrefix(); 5559243Sobrien 5659243Sobrien if (MO.isGlobal()) { 5759243Sobrien const GlobalValue *GV = MO.getGlobal(); 5859243Sobrien AsmPrinter.getNameWithPrefix(Name, GV); 5959243Sobrien } else if (MO.isSymbol()) { 6059243Sobrien Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 6159243Sobrien } else if (MO.isMBB()) { 6259243Sobrien assert(Suffix.empty()); 6359243Sobrien Sym = MO.getMBB()->getSymbol(); 6459243Sobrien } 6559243Sobrien 6659243Sobrien Name += Suffix; 6759243Sobrien if (!Sym) 6859243Sobrien Sym = Ctx.getOrCreateSymbol(Name); 6959243Sobrien 7059243Sobrien return Sym; 7159243Sobrien} 7259243Sobrien 7359243SobrienMCOperand M68kMCInstLower::LowerSymbolOperand(const MachineOperand &MO, 7459243Sobrien MCSymbol *Sym) const { 7559243Sobrien // FIXME We would like an efficient form for this, so we don't have to do a 7659243Sobrien // lot of extra uniquing. This fixme is originally from X86 7759243Sobrien const MCExpr *Expr = nullptr; 7859243Sobrien MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 7959243Sobrien 8059243Sobrien switch (MO.getTargetFlags()) { 8159243Sobrien default: 8259243Sobrien llvm_unreachable("Unknown target flag on GV operand"); 8359243Sobrien case M68kII::MO_NO_FLAG: 8459243Sobrien case M68kII::MO_ABSOLUTE_ADDRESS: 8559243Sobrien case M68kII::MO_PC_RELATIVE_ADDRESS: 8659243Sobrien break; 8759243Sobrien case M68kII::MO_GOTPCREL: 8859243Sobrien RefKind = MCSymbolRefExpr::VK_GOTPCREL; 8959243Sobrien break; 9059243Sobrien case M68kII::MO_GOT: 9159243Sobrien RefKind = MCSymbolRefExpr::VK_GOT; 9259243Sobrien break; 9359243Sobrien case M68kII::MO_GOTOFF: 9459243Sobrien RefKind = MCSymbolRefExpr::VK_GOTOFF; 9559243Sobrien break; 9659243Sobrien case M68kII::MO_PLT: 9759243Sobrien RefKind = MCSymbolRefExpr::VK_PLT; 9859243Sobrien break; 9959243Sobrien case M68kII::MO_TLSGD: 10059243Sobrien RefKind = MCSymbolRefExpr::VK_TLSGD; 10159243Sobrien break; 10259243Sobrien case M68kII::MO_TLSLD: 10359243Sobrien RefKind = MCSymbolRefExpr::VK_TLSLD; 10459243Sobrien break; 10559243Sobrien case M68kII::MO_TLSLDM: 10659243Sobrien RefKind = MCSymbolRefExpr::VK_TLSLDM; 10759243Sobrien break; 10859243Sobrien case M68kII::MO_TLSIE: 10959243Sobrien RefKind = MCSymbolRefExpr::VK_GOTTPOFF; 11059243Sobrien break; 11159243Sobrien case M68kII::MO_TLSLE: 11259243Sobrien RefKind = MCSymbolRefExpr::VK_TPOFF; 11359243Sobrien break; 11459243Sobrien } 11559243Sobrien 11659243Sobrien if (!Expr) { 11759243Sobrien Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); 11859243Sobrien } 11959243Sobrien 12059243Sobrien if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) { 12159243Sobrien Expr = MCBinaryExpr::createAdd( 12259243Sobrien Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 12359243Sobrien } 12459243Sobrien 12559243Sobrien return MCOperand::createExpr(Expr); 12659243Sobrien} 12759243Sobrien 12859243Sobrienstd::optional<MCOperand> 12959243SobrienM68kMCInstLower::LowerOperand(const MachineInstr *MI, 13059243Sobrien const MachineOperand &MO) const { 13159243Sobrien switch (MO.getType()) { 13259243Sobrien default: 13359243Sobrien llvm_unreachable("unknown operand type"); 13459243Sobrien case MachineOperand::MO_Register: 13559243Sobrien // Ignore all implicit register operands. 13659243Sobrien if (MO.isImplicit()) 13759243Sobrien return std::nullopt; 13859243Sobrien return MCOperand::createReg(MO.getReg()); 13959243Sobrien case MachineOperand::MO_Immediate: 14059243Sobrien return MCOperand::createImm(MO.getImm()); 14159243Sobrien case MachineOperand::MO_MachineBasicBlock: 14259243Sobrien case MachineOperand::MO_GlobalAddress: 14359243Sobrien case MachineOperand::MO_ExternalSymbol: 14459243Sobrien return LowerSymbolOperand(MO, GetSymbolFromOperand(MO)); 14559243Sobrien case MachineOperand::MO_MCSymbol: 14659243Sobrien return LowerSymbolOperand(MO, MO.getMCSymbol()); 14759243Sobrien case MachineOperand::MO_JumpTableIndex: 14859243Sobrien return LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex())); 14959243Sobrien case MachineOperand::MO_ConstantPoolIndex: 15059243Sobrien return LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex())); 15159243Sobrien case MachineOperand::MO_BlockAddress: 15259243Sobrien return LowerSymbolOperand( 15359243Sobrien MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress())); 15459243Sobrien case MachineOperand::MO_RegisterMask: 15559243Sobrien // Ignore call clobbers. 15659243Sobrien return std::nullopt; 15759243Sobrien } 15859243Sobrien} 15959243Sobrien 16059243Sobrienvoid M68kMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 16159243Sobrien unsigned Opcode = MI->getOpcode(); 16259243Sobrien OutMI.setOpcode(Opcode); 16359243Sobrien 16459243Sobrien for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 16559243Sobrien const MachineOperand &MO = MI->getOperand(i); 16659243Sobrien std::optional<MCOperand> MCOp = LowerOperand(MI, MO); 16759243Sobrien 16859243Sobrien if (MCOp.has_value() && MCOp.value().isValid()) 16959243Sobrien OutMI.addOperand(MCOp.value()); 17059243Sobrien } 17159243Sobrien 17259243Sobrien // TAILJMPj, TAILJMPq - Lower to the correct jump instructions. 17359243Sobrien if (Opcode == M68k::TAILJMPj || Opcode == M68k::TAILJMPq) { 17459243Sobrien assert(OutMI.getNumOperands() == 1 && "Unexpected number of operands"); 17559243Sobrien switch (Opcode) { 17659243Sobrien case M68k::TAILJMPj: 17759243Sobrien Opcode = M68k::JMP32j; 17859243Sobrien break; 17959243Sobrien case M68k::TAILJMPq: 18059243Sobrien Opcode = M68k::BRA8; 18159243Sobrien break; 18259243Sobrien } 18359243Sobrien OutMI.setOpcode(Opcode); 18459243Sobrien } 18559243Sobrien} 18659243Sobrien