1*0b57cec5SDimitry Andric //===- HexagonMCInstLower.cpp - Convert Hexagon MachineInstr to an MCInst -===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains code to lower Hexagon MachineInstrs to their corresponding 10*0b57cec5SDimitry Andric // MCInst records. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "Hexagon.h" 15*0b57cec5SDimitry Andric #include "HexagonAsmPrinter.h" 16*0b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCExpr.h" 17*0b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h" 18*0b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 20*0b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 24*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 25*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 26*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 27*0b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 28*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 29*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 30*0b57cec5SDimitry Andric #include <cassert> 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric using namespace llvm; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric namespace llvm { 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, 37*0b57cec5SDimitry Andric MCInst &MCB, HexagonAsmPrinter &AP); 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric } // end namespace llvm 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 42*0b57cec5SDimitry Andric HexagonAsmPrinter &Printer, bool MustExtend) { 43*0b57cec5SDimitry Andric MCContext &MC = Printer.OutContext; 44*0b57cec5SDimitry Andric const MCExpr *ME; 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric // Populate the relocation type based on Hexagon target flags 47*0b57cec5SDimitry Andric // set on an operand 48*0b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RelocationType; 49*0b57cec5SDimitry Andric switch (MO.getTargetFlags() & ~HexagonII::HMOTF_ConstExtended) { 50*0b57cec5SDimitry Andric default: 51*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_None; 52*0b57cec5SDimitry Andric break; 53*0b57cec5SDimitry Andric case HexagonII::MO_PCREL: 54*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_PCREL; 55*0b57cec5SDimitry Andric break; 56*0b57cec5SDimitry Andric case HexagonII::MO_GOT: 57*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_GOT; 58*0b57cec5SDimitry Andric break; 59*0b57cec5SDimitry Andric case HexagonII::MO_LO16: 60*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_LO16; 61*0b57cec5SDimitry Andric break; 62*0b57cec5SDimitry Andric case HexagonII::MO_HI16: 63*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_HI16; 64*0b57cec5SDimitry Andric break; 65*0b57cec5SDimitry Andric case HexagonII::MO_GPREL: 66*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_GPREL; 67*0b57cec5SDimitry Andric break; 68*0b57cec5SDimitry Andric case HexagonII::MO_GDGOT: 69*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_GOT; 70*0b57cec5SDimitry Andric break; 71*0b57cec5SDimitry Andric case HexagonII::MO_GDPLT: 72*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_PLT; 73*0b57cec5SDimitry Andric break; 74*0b57cec5SDimitry Andric case HexagonII::MO_IE: 75*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_IE; 76*0b57cec5SDimitry Andric break; 77*0b57cec5SDimitry Andric case HexagonII::MO_IEGOT: 78*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_IE_GOT; 79*0b57cec5SDimitry Andric break; 80*0b57cec5SDimitry Andric case HexagonII::MO_TPREL: 81*0b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_TPREL; 82*0b57cec5SDimitry Andric break; 83*0b57cec5SDimitry Andric } 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric ME = MCSymbolRefExpr::create(Symbol, RelocationType, MC); 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 88*0b57cec5SDimitry Andric ME = MCBinaryExpr::createAdd(ME, MCConstantExpr::create(MO.getOffset(), MC), 89*0b57cec5SDimitry Andric MC); 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric ME = HexagonMCExpr::create(ME, MC); 92*0b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*ME, MustExtend); 93*0b57cec5SDimitry Andric return MCOperand::createExpr(ME); 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric // Create an MCInst from a MachineInstr 97*0b57cec5SDimitry Andric void llvm::HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, 98*0b57cec5SDimitry Andric MCInst &MCB, HexagonAsmPrinter &AP) { 99*0b57cec5SDimitry Andric if (MI->getOpcode() == Hexagon::ENDLOOP0) { 100*0b57cec5SDimitry Andric HexagonMCInstrInfo::setInnerLoop(MCB); 101*0b57cec5SDimitry Andric return; 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric if (MI->getOpcode() == Hexagon::ENDLOOP1) { 104*0b57cec5SDimitry Andric HexagonMCInstrInfo::setOuterLoop(MCB); 105*0b57cec5SDimitry Andric return; 106*0b57cec5SDimitry Andric } 107*0b57cec5SDimitry Andric MCInst *MCI = new (AP.OutContext) MCInst; 108*0b57cec5SDimitry Andric MCI->setOpcode(MI->getOpcode()); 109*0b57cec5SDimitry Andric assert(MCI->getOpcode() == static_cast<unsigned>(MI->getOpcode()) && 110*0b57cec5SDimitry Andric "MCI opcode should have been set on construction"); 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { 113*0b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(i); 114*0b57cec5SDimitry Andric MCOperand MCO; 115*0b57cec5SDimitry Andric bool MustExtend = MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended; 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric switch (MO.getType()) { 118*0b57cec5SDimitry Andric default: 119*0b57cec5SDimitry Andric MI->print(errs()); 120*0b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 121*0b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 122*0b57cec5SDimitry Andric continue; 123*0b57cec5SDimitry Andric case MachineOperand::MO_Register: 124*0b57cec5SDimitry Andric // Ignore all implicit register operands. 125*0b57cec5SDimitry Andric if (MO.isImplicit()) 126*0b57cec5SDimitry Andric continue; 127*0b57cec5SDimitry Andric MCO = MCOperand::createReg(MO.getReg()); 128*0b57cec5SDimitry Andric break; 129*0b57cec5SDimitry Andric case MachineOperand::MO_FPImmediate: { 130*0b57cec5SDimitry Andric APFloat Val = MO.getFPImm()->getValueAPF(); 131*0b57cec5SDimitry Andric // FP immediates are used only when setting GPRs, so they may be dealt 132*0b57cec5SDimitry Andric // with like regular immediates from this point on. 133*0b57cec5SDimitry Andric auto Expr = HexagonMCExpr::create( 134*0b57cec5SDimitry Andric MCConstantExpr::create(*Val.bitcastToAPInt().getRawData(), 135*0b57cec5SDimitry Andric AP.OutContext), 136*0b57cec5SDimitry Andric AP.OutContext); 137*0b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); 138*0b57cec5SDimitry Andric MCO = MCOperand::createExpr(Expr); 139*0b57cec5SDimitry Andric break; 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric case MachineOperand::MO_Immediate: { 142*0b57cec5SDimitry Andric auto Expr = HexagonMCExpr::create( 143*0b57cec5SDimitry Andric MCConstantExpr::create(MO.getImm(), AP.OutContext), AP.OutContext); 144*0b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); 145*0b57cec5SDimitry Andric MCO = MCOperand::createExpr(Expr); 146*0b57cec5SDimitry Andric break; 147*0b57cec5SDimitry Andric } 148*0b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: { 149*0b57cec5SDimitry Andric MCExpr const *Expr = MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), 150*0b57cec5SDimitry Andric AP.OutContext); 151*0b57cec5SDimitry Andric Expr = HexagonMCExpr::create(Expr, AP.OutContext); 152*0b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); 153*0b57cec5SDimitry Andric MCO = MCOperand::createExpr(Expr); 154*0b57cec5SDimitry Andric break; 155*0b57cec5SDimitry Andric } 156*0b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 157*0b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP, MustExtend); 158*0b57cec5SDimitry Andric break; 159*0b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 160*0b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), 161*0b57cec5SDimitry Andric AP, MustExtend); 162*0b57cec5SDimitry Andric break; 163*0b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 164*0b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, MustExtend); 165*0b57cec5SDimitry Andric break; 166*0b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 167*0b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, MustExtend); 168*0b57cec5SDimitry Andric break; 169*0b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 170*0b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP, 171*0b57cec5SDimitry Andric MustExtend); 172*0b57cec5SDimitry Andric break; 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric MCI->addOperand(MCO); 176*0b57cec5SDimitry Andric } 177*0b57cec5SDimitry Andric AP.HexagonProcessInstruction(*MCI, *MI); 178*0b57cec5SDimitry Andric HexagonMCInstrInfo::extendIfNeeded(AP.OutContext, MCII, MCB, *MCI); 179*0b57cec5SDimitry Andric MCB.addOperand(MCOperand::createInst(MCI)); 180*0b57cec5SDimitry Andric } 181