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