1*04eeddc0SDimitry Andric //===-- M68kMCInstLower.cpp - M68k MachineInstr to MCInst -------*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric /// 9fe6060f1SDimitry Andric /// \file 10fe6060f1SDimitry Andric /// This file contains code to lower M68k MachineInstrs to their 11fe6060f1SDimitry Andric /// corresponding MCInst records. 12fe6060f1SDimitry Andric /// 13fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 14fe6060f1SDimitry Andric 15fe6060f1SDimitry Andric #include "M68kMCInstLower.h" 16fe6060f1SDimitry Andric 17fe6060f1SDimitry Andric #include "M68kAsmPrinter.h" 18fe6060f1SDimitry Andric #include "M68kInstrInfo.h" 19fe6060f1SDimitry Andric 20fe6060f1SDimitry Andric #include "MCTargetDesc/M68kBaseInfo.h" 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 23fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 24fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 25fe6060f1SDimitry Andric #include "llvm/IR/Mangler.h" 26fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h" 27fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h" 28fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h" 29fe6060f1SDimitry Andric 30fe6060f1SDimitry Andric using namespace llvm; 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k-mc-inst-lower" 33fe6060f1SDimitry Andric 34fe6060f1SDimitry Andric M68kMCInstLower::M68kMCInstLower(MachineFunction &MF, M68kAsmPrinter &AP) 35fe6060f1SDimitry Andric : Ctx(MF.getContext()), MF(MF), TM(MF.getTarget()), MAI(*TM.getMCAsmInfo()), 36fe6060f1SDimitry Andric AsmPrinter(AP) {} 37fe6060f1SDimitry Andric 38fe6060f1SDimitry Andric MCSymbol * 39fe6060f1SDimitry Andric M68kMCInstLower::GetSymbolFromOperand(const MachineOperand &MO) const { 40fe6060f1SDimitry Andric assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) && 41fe6060f1SDimitry Andric "Isn't a symbol reference"); 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric const auto &TT = TM.getTargetTriple(); 44fe6060f1SDimitry Andric if (MO.isGlobal() && TT.isOSBinFormatELF()) 45fe6060f1SDimitry Andric return AsmPrinter.getSymbolPreferLocal(*MO.getGlobal()); 46fe6060f1SDimitry Andric 47fe6060f1SDimitry Andric const DataLayout &DL = MF.getDataLayout(); 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric MCSymbol *Sym = nullptr; 50fe6060f1SDimitry Andric SmallString<128> Name; 51fe6060f1SDimitry Andric StringRef Suffix; 52fe6060f1SDimitry Andric 53fe6060f1SDimitry Andric if (!Suffix.empty()) 54fe6060f1SDimitry Andric Name += DL.getPrivateGlobalPrefix(); 55fe6060f1SDimitry Andric 56fe6060f1SDimitry Andric if (MO.isGlobal()) { 57fe6060f1SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 58fe6060f1SDimitry Andric AsmPrinter.getNameWithPrefix(Name, GV); 59fe6060f1SDimitry Andric } else if (MO.isSymbol()) { 60fe6060f1SDimitry Andric Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); 61fe6060f1SDimitry Andric } else if (MO.isMBB()) { 62fe6060f1SDimitry Andric assert(Suffix.empty()); 63fe6060f1SDimitry Andric Sym = MO.getMBB()->getSymbol(); 64fe6060f1SDimitry Andric } 65fe6060f1SDimitry Andric 66fe6060f1SDimitry Andric Name += Suffix; 67fe6060f1SDimitry Andric if (!Sym) 68fe6060f1SDimitry Andric Sym = Ctx.getOrCreateSymbol(Name); 69fe6060f1SDimitry Andric 70fe6060f1SDimitry Andric return Sym; 71fe6060f1SDimitry Andric } 72fe6060f1SDimitry Andric 73fe6060f1SDimitry Andric MCOperand M68kMCInstLower::LowerSymbolOperand(const MachineOperand &MO, 74fe6060f1SDimitry Andric MCSymbol *Sym) const { 75fe6060f1SDimitry Andric // FIXME We would like an efficient form for this, so we don't have to do a 76fe6060f1SDimitry Andric // lot of extra uniquing. This fixme is originally from X86 77fe6060f1SDimitry Andric const MCExpr *Expr = nullptr; 78fe6060f1SDimitry Andric MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric switch (MO.getTargetFlags()) { 81fe6060f1SDimitry Andric default: 82fe6060f1SDimitry Andric llvm_unreachable("Unknown target flag on GV operand"); 83fe6060f1SDimitry Andric case M68kII::MO_NO_FLAG: 84fe6060f1SDimitry Andric case M68kII::MO_ABSOLUTE_ADDRESS: 85fe6060f1SDimitry Andric case M68kII::MO_PC_RELATIVE_ADDRESS: 86fe6060f1SDimitry Andric break; 87fe6060f1SDimitry Andric case M68kII::MO_GOTPCREL: 88fe6060f1SDimitry Andric RefKind = MCSymbolRefExpr::VK_GOTPCREL; 89fe6060f1SDimitry Andric break; 90fe6060f1SDimitry Andric case M68kII::MO_GOT: 91fe6060f1SDimitry Andric RefKind = MCSymbolRefExpr::VK_GOT; 92fe6060f1SDimitry Andric break; 93fe6060f1SDimitry Andric case M68kII::MO_GOTOFF: 94fe6060f1SDimitry Andric RefKind = MCSymbolRefExpr::VK_GOTOFF; 95fe6060f1SDimitry Andric break; 96fe6060f1SDimitry Andric case M68kII::MO_PLT: 97fe6060f1SDimitry Andric RefKind = MCSymbolRefExpr::VK_PLT; 98fe6060f1SDimitry Andric break; 99fe6060f1SDimitry Andric } 100fe6060f1SDimitry Andric 101fe6060f1SDimitry Andric if (!Expr) { 102fe6060f1SDimitry Andric Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); 103fe6060f1SDimitry Andric } 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) { 106fe6060f1SDimitry Andric Expr = MCBinaryExpr::createAdd( 107fe6060f1SDimitry Andric Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 108fe6060f1SDimitry Andric } 109fe6060f1SDimitry Andric 110fe6060f1SDimitry Andric return MCOperand::createExpr(Expr); 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric 113fe6060f1SDimitry Andric Optional<MCOperand> 114fe6060f1SDimitry Andric M68kMCInstLower::LowerOperand(const MachineInstr *MI, 115fe6060f1SDimitry Andric const MachineOperand &MO) const { 116fe6060f1SDimitry Andric switch (MO.getType()) { 117fe6060f1SDimitry Andric default: 118fe6060f1SDimitry Andric llvm_unreachable("unknown operand type"); 119fe6060f1SDimitry Andric case MachineOperand::MO_Register: 120fe6060f1SDimitry Andric // Ignore all implicit register operands. 121fe6060f1SDimitry Andric if (MO.isImplicit()) 122fe6060f1SDimitry Andric return None; 123fe6060f1SDimitry Andric return MCOperand::createReg(MO.getReg()); 124fe6060f1SDimitry Andric case MachineOperand::MO_Immediate: 125fe6060f1SDimitry Andric return MCOperand::createImm(MO.getImm()); 126fe6060f1SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 127fe6060f1SDimitry Andric case MachineOperand::MO_GlobalAddress: 128fe6060f1SDimitry Andric case MachineOperand::MO_ExternalSymbol: 129fe6060f1SDimitry Andric return LowerSymbolOperand(MO, GetSymbolFromOperand(MO)); 130fe6060f1SDimitry Andric case MachineOperand::MO_MCSymbol: 131fe6060f1SDimitry Andric return LowerSymbolOperand(MO, MO.getMCSymbol()); 132fe6060f1SDimitry Andric case MachineOperand::MO_JumpTableIndex: 133fe6060f1SDimitry Andric return LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex())); 134fe6060f1SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 135fe6060f1SDimitry Andric return LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex())); 136fe6060f1SDimitry Andric case MachineOperand::MO_BlockAddress: 137fe6060f1SDimitry Andric return LowerSymbolOperand( 138fe6060f1SDimitry Andric MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress())); 139fe6060f1SDimitry Andric case MachineOperand::MO_RegisterMask: 140fe6060f1SDimitry Andric // Ignore call clobbers. 141fe6060f1SDimitry Andric return None; 142fe6060f1SDimitry Andric } 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric 145fe6060f1SDimitry Andric void M68kMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 146fe6060f1SDimitry Andric unsigned Opcode = MI->getOpcode(); 147fe6060f1SDimitry Andric OutMI.setOpcode(Opcode); 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 150fe6060f1SDimitry Andric const MachineOperand &MO = MI->getOperand(i); 151fe6060f1SDimitry Andric Optional<MCOperand> MCOp = LowerOperand(MI, MO); 152fe6060f1SDimitry Andric 153fe6060f1SDimitry Andric if (MCOp.hasValue() && MCOp.getValue().isValid()) 154fe6060f1SDimitry Andric OutMI.addOperand(MCOp.getValue()); 155fe6060f1SDimitry Andric } 156fe6060f1SDimitry Andric 157fe6060f1SDimitry Andric // TAILJMPj, TAILJMPq - Lower to the correct jump instructions. 158fe6060f1SDimitry Andric if (Opcode == M68k::TAILJMPj || Opcode == M68k::TAILJMPq) { 159fe6060f1SDimitry Andric assert(OutMI.getNumOperands() == 1 && "Unexpected number of operands"); 160fe6060f1SDimitry Andric switch (Opcode) { 161fe6060f1SDimitry Andric case M68k::TAILJMPj: 162fe6060f1SDimitry Andric Opcode = M68k::JMP32j; 163fe6060f1SDimitry Andric break; 164fe6060f1SDimitry Andric case M68k::TAILJMPq: 165fe6060f1SDimitry Andric Opcode = M68k::BRA8; 166fe6060f1SDimitry Andric break; 167fe6060f1SDimitry Andric } 168fe6060f1SDimitry Andric OutMI.setOpcode(Opcode); 169fe6060f1SDimitry Andric } 170fe6060f1SDimitry Andric } 171