10b57cec5SDimitry Andric //===- HexagonMCInstLower.cpp - Convert Hexagon MachineInstr to an MCInst -===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains code to lower Hexagon MachineInstrs to their corresponding 100b57cec5SDimitry Andric // MCInst records. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "Hexagon.h" 150b57cec5SDimitry Andric #include "HexagonAsmPrinter.h" 160b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCExpr.h" 170b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h" 180b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h" 190b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 200b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 240b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 280b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric #include <cassert> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric using namespace llvm; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric namespace llvm { 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, 370b57cec5SDimitry Andric MCInst &MCB, HexagonAsmPrinter &AP); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric } // end namespace llvm 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, 420b57cec5SDimitry Andric HexagonAsmPrinter &Printer, bool MustExtend) { 430b57cec5SDimitry Andric MCContext &MC = Printer.OutContext; 440b57cec5SDimitry Andric const MCExpr *ME; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric // Populate the relocation type based on Hexagon target flags 470b57cec5SDimitry Andric // set on an operand 480b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RelocationType; 490b57cec5SDimitry Andric switch (MO.getTargetFlags() & ~HexagonII::HMOTF_ConstExtended) { 500b57cec5SDimitry Andric default: 510b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_None; 520b57cec5SDimitry Andric break; 530b57cec5SDimitry Andric case HexagonII::MO_PCREL: 54*5ffd83dbSDimitry Andric RelocationType = MCSymbolRefExpr::VK_PCREL; 550b57cec5SDimitry Andric break; 560b57cec5SDimitry Andric case HexagonII::MO_GOT: 570b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_GOT; 580b57cec5SDimitry Andric break; 590b57cec5SDimitry Andric case HexagonII::MO_LO16: 600b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_LO16; 610b57cec5SDimitry Andric break; 620b57cec5SDimitry Andric case HexagonII::MO_HI16: 630b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_HI16; 640b57cec5SDimitry Andric break; 650b57cec5SDimitry Andric case HexagonII::MO_GPREL: 660b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_GPREL; 670b57cec5SDimitry Andric break; 680b57cec5SDimitry Andric case HexagonII::MO_GDGOT: 690b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_GOT; 700b57cec5SDimitry Andric break; 710b57cec5SDimitry Andric case HexagonII::MO_GDPLT: 720b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_PLT; 730b57cec5SDimitry Andric break; 740b57cec5SDimitry Andric case HexagonII::MO_IE: 750b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_IE; 760b57cec5SDimitry Andric break; 770b57cec5SDimitry Andric case HexagonII::MO_IEGOT: 780b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_Hexagon_IE_GOT; 790b57cec5SDimitry Andric break; 800b57cec5SDimitry Andric case HexagonII::MO_TPREL: 810b57cec5SDimitry Andric RelocationType = MCSymbolRefExpr::VK_TPREL; 820b57cec5SDimitry Andric break; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric ME = MCSymbolRefExpr::create(Symbol, RelocationType, MC); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 880b57cec5SDimitry Andric ME = MCBinaryExpr::createAdd(ME, MCConstantExpr::create(MO.getOffset(), MC), 890b57cec5SDimitry Andric MC); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric ME = HexagonMCExpr::create(ME, MC); 920b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*ME, MustExtend); 930b57cec5SDimitry Andric return MCOperand::createExpr(ME); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric // Create an MCInst from a MachineInstr 970b57cec5SDimitry Andric void llvm::HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, 980b57cec5SDimitry Andric MCInst &MCB, HexagonAsmPrinter &AP) { 990b57cec5SDimitry Andric if (MI->getOpcode() == Hexagon::ENDLOOP0) { 1000b57cec5SDimitry Andric HexagonMCInstrInfo::setInnerLoop(MCB); 1010b57cec5SDimitry Andric return; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric if (MI->getOpcode() == Hexagon::ENDLOOP1) { 1040b57cec5SDimitry Andric HexagonMCInstrInfo::setOuterLoop(MCB); 1050b57cec5SDimitry Andric return; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric MCInst *MCI = new (AP.OutContext) MCInst; 1080b57cec5SDimitry Andric MCI->setOpcode(MI->getOpcode()); 1090b57cec5SDimitry Andric assert(MCI->getOpcode() == static_cast<unsigned>(MI->getOpcode()) && 1100b57cec5SDimitry Andric "MCI opcode should have been set on construction"); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { 1130b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(i); 1140b57cec5SDimitry Andric MCOperand MCO; 1150b57cec5SDimitry Andric bool MustExtend = MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric switch (MO.getType()) { 1180b57cec5SDimitry Andric default: 1190b57cec5SDimitry Andric MI->print(errs()); 1200b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 1210b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 1220b57cec5SDimitry Andric continue; 1230b57cec5SDimitry Andric case MachineOperand::MO_Register: 1240b57cec5SDimitry Andric // Ignore all implicit register operands. 1250b57cec5SDimitry Andric if (MO.isImplicit()) 1260b57cec5SDimitry Andric continue; 1270b57cec5SDimitry Andric MCO = MCOperand::createReg(MO.getReg()); 1280b57cec5SDimitry Andric break; 1290b57cec5SDimitry Andric case MachineOperand::MO_FPImmediate: { 1300b57cec5SDimitry Andric APFloat Val = MO.getFPImm()->getValueAPF(); 1310b57cec5SDimitry Andric // FP immediates are used only when setting GPRs, so they may be dealt 1320b57cec5SDimitry Andric // with like regular immediates from this point on. 1330b57cec5SDimitry Andric auto Expr = HexagonMCExpr::create( 1340b57cec5SDimitry Andric MCConstantExpr::create(*Val.bitcastToAPInt().getRawData(), 1350b57cec5SDimitry Andric AP.OutContext), 1360b57cec5SDimitry Andric AP.OutContext); 1370b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); 1380b57cec5SDimitry Andric MCO = MCOperand::createExpr(Expr); 1390b57cec5SDimitry Andric break; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric case MachineOperand::MO_Immediate: { 1420b57cec5SDimitry Andric auto Expr = HexagonMCExpr::create( 1430b57cec5SDimitry Andric MCConstantExpr::create(MO.getImm(), AP.OutContext), AP.OutContext); 1440b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); 1450b57cec5SDimitry Andric MCO = MCOperand::createExpr(Expr); 1460b57cec5SDimitry Andric break; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: { 1490b57cec5SDimitry Andric MCExpr const *Expr = MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), 1500b57cec5SDimitry Andric AP.OutContext); 1510b57cec5SDimitry Andric Expr = HexagonMCExpr::create(Expr, AP.OutContext); 1520b57cec5SDimitry Andric HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); 1530b57cec5SDimitry Andric MCO = MCOperand::createExpr(Expr); 1540b57cec5SDimitry Andric break; 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 1570b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP, MustExtend); 1580b57cec5SDimitry Andric break; 1590b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 1600b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), 1610b57cec5SDimitry Andric AP, MustExtend); 1620b57cec5SDimitry Andric break; 1630b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 1640b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, MustExtend); 1650b57cec5SDimitry Andric break; 1660b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 1670b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, MustExtend); 1680b57cec5SDimitry Andric break; 1690b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 1700b57cec5SDimitry Andric MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP, 1710b57cec5SDimitry Andric MustExtend); 1720b57cec5SDimitry Andric break; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric MCI->addOperand(MCO); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric AP.HexagonProcessInstruction(*MCI, *MI); 1780b57cec5SDimitry Andric HexagonMCInstrInfo::extendIfNeeded(AP.OutContext, MCII, MCB, *MCI); 1790b57cec5SDimitry Andric MCB.addOperand(MCOperand::createInst(MCI)); 1800b57cec5SDimitry Andric } 181