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 } 100 101 if (!Expr) { 102 Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); 103 } 104 105 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) { 106 Expr = MCBinaryExpr::createAdd( 107 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 108 } 109 110 return MCOperand::createExpr(Expr); 111 } 112 113 Optional<MCOperand> 114 M68kMCInstLower::LowerOperand(const MachineInstr *MI, 115 const MachineOperand &MO) const { 116 switch (MO.getType()) { 117 default: 118 llvm_unreachable("unknown operand type"); 119 case MachineOperand::MO_Register: 120 // Ignore all implicit register operands. 121 if (MO.isImplicit()) 122 return None; 123 return MCOperand::createReg(MO.getReg()); 124 case MachineOperand::MO_Immediate: 125 return MCOperand::createImm(MO.getImm()); 126 case MachineOperand::MO_MachineBasicBlock: 127 case MachineOperand::MO_GlobalAddress: 128 case MachineOperand::MO_ExternalSymbol: 129 return LowerSymbolOperand(MO, GetSymbolFromOperand(MO)); 130 case MachineOperand::MO_MCSymbol: 131 return LowerSymbolOperand(MO, MO.getMCSymbol()); 132 case MachineOperand::MO_JumpTableIndex: 133 return LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex())); 134 case MachineOperand::MO_ConstantPoolIndex: 135 return LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex())); 136 case MachineOperand::MO_BlockAddress: 137 return LowerSymbolOperand( 138 MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress())); 139 case MachineOperand::MO_RegisterMask: 140 // Ignore call clobbers. 141 return None; 142 } 143 } 144 145 void M68kMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 146 unsigned Opcode = MI->getOpcode(); 147 OutMI.setOpcode(Opcode); 148 149 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 150 const MachineOperand &MO = MI->getOperand(i); 151 Optional<MCOperand> MCOp = LowerOperand(MI, MO); 152 153 if (MCOp.hasValue() && MCOp.getValue().isValid()) 154 OutMI.addOperand(MCOp.getValue()); 155 } 156 157 // TAILJMPj, TAILJMPq - Lower to the correct jump instructions. 158 if (Opcode == M68k::TAILJMPj || Opcode == M68k::TAILJMPq) { 159 assert(OutMI.getNumOperands() == 1 && "Unexpected number of operands"); 160 switch (Opcode) { 161 case M68k::TAILJMPj: 162 Opcode = M68k::JMP32j; 163 break; 164 case M68k::TAILJMPq: 165 Opcode = M68k::BRA8; 166 break; 167 } 168 OutMI.setOpcode(Opcode); 169 } 170 } 171