| //===- HexagonMCInstLower.cpp - Convert Hexagon MachineInstr to an MCInst -===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file contains code to lower Hexagon MachineInstrs to their corresponding | |
| // MCInst records. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "Hexagon.h" | |
| #include "HexagonAsmPrinter.h" | |
| #include "MCTargetDesc/HexagonMCExpr.h" | |
| #include "MCTargetDesc/HexagonMCInstrInfo.h" | |
| #include "MCTargetDesc/HexagonMCTargetDesc.h" | |
| #include "llvm/ADT/APFloat.h" | |
| #include "llvm/ADT/APInt.h" | |
| #include "llvm/CodeGen/MachineBasicBlock.h" | |
| #include "llvm/CodeGen/MachineInstr.h" | |
| #include "llvm/CodeGen/MachineOperand.h" | |
| #include "llvm/IR/Constants.h" | |
| #include "llvm/MC/MCContext.h" | |
| #include "llvm/MC/MCExpr.h" | |
| #include "llvm/MC/MCInst.h" | |
| #include "llvm/Support/ErrorHandling.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include <cassert> | |
| using namespace llvm; | |
| namespace llvm { | |
| void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, | |
| MCInst &MCB, HexagonAsmPrinter &AP); | |
| } // end namespace llvm | |
| static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, | |
| HexagonAsmPrinter &Printer, bool MustExtend) { | |
| MCContext &MC = Printer.OutContext; | |
| const MCExpr *ME; | |
| // Populate the relocation type based on Hexagon target flags | |
| // set on an operand | |
| MCSymbolRefExpr::VariantKind RelocationType; | |
| switch (MO.getTargetFlags() & ~HexagonII::HMOTF_ConstExtended) { | |
| default: | |
| RelocationType = MCSymbolRefExpr::VK_None; | |
| break; | |
| case HexagonII::MO_PCREL: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_PCREL; | |
| break; | |
| case HexagonII::MO_GOT: | |
| RelocationType = MCSymbolRefExpr::VK_GOT; | |
| break; | |
| case HexagonII::MO_LO16: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_LO16; | |
| break; | |
| case HexagonII::MO_HI16: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_HI16; | |
| break; | |
| case HexagonII::MO_GPREL: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_GPREL; | |
| break; | |
| case HexagonII::MO_GDGOT: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_GOT; | |
| break; | |
| case HexagonII::MO_GDPLT: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_PLT; | |
| break; | |
| case HexagonII::MO_IE: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_IE; | |
| break; | |
| case HexagonII::MO_IEGOT: | |
| RelocationType = MCSymbolRefExpr::VK_Hexagon_IE_GOT; | |
| break; | |
| case HexagonII::MO_TPREL: | |
| RelocationType = MCSymbolRefExpr::VK_TPREL; | |
| break; | |
| } | |
| ME = MCSymbolRefExpr::create(Symbol, RelocationType, MC); | |
| if (!MO.isJTI() && MO.getOffset()) | |
| ME = MCBinaryExpr::createAdd(ME, MCConstantExpr::create(MO.getOffset(), MC), | |
| MC); | |
| ME = HexagonMCExpr::create(ME, MC); | |
| HexagonMCInstrInfo::setMustExtend(*ME, MustExtend); | |
| return MCOperand::createExpr(ME); | |
| } | |
| // Create an MCInst from a MachineInstr | |
| void llvm::HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, | |
| MCInst &MCB, HexagonAsmPrinter &AP) { | |
| if (MI->getOpcode() == Hexagon::ENDLOOP0) { | |
| HexagonMCInstrInfo::setInnerLoop(MCB); | |
| return; | |
| } | |
| if (MI->getOpcode() == Hexagon::ENDLOOP1) { | |
| HexagonMCInstrInfo::setOuterLoop(MCB); | |
| return; | |
| } | |
| MCInst *MCI = new (AP.OutContext) MCInst; | |
| MCI->setOpcode(MI->getOpcode()); | |
| assert(MCI->getOpcode() == static_cast<unsigned>(MI->getOpcode()) && | |
| "MCI opcode should have been set on construction"); | |
| for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { | |
| const MachineOperand &MO = MI->getOperand(i); | |
| MCOperand MCO; | |
| bool MustExtend = MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended; | |
| switch (MO.getType()) { | |
| default: | |
| MI->print(errs()); | |
| llvm_unreachable("unknown operand type"); | |
| case MachineOperand::MO_RegisterMask: | |
| continue; | |
| case MachineOperand::MO_Register: | |
| // Ignore all implicit register operands. | |
| if (MO.isImplicit()) | |
| continue; | |
| MCO = MCOperand::createReg(MO.getReg()); | |
| break; | |
| case MachineOperand::MO_FPImmediate: { | |
| APFloat Val = MO.getFPImm()->getValueAPF(); | |
| // FP immediates are used only when setting GPRs, so they may be dealt | |
| // with like regular immediates from this point on. | |
| auto Expr = HexagonMCExpr::create( | |
| MCConstantExpr::create(*Val.bitcastToAPInt().getRawData(), | |
| AP.OutContext), | |
| AP.OutContext); | |
| HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); | |
| MCO = MCOperand::createExpr(Expr); | |
| break; | |
| } | |
| case MachineOperand::MO_Immediate: { | |
| auto Expr = HexagonMCExpr::create( | |
| MCConstantExpr::create(MO.getImm(), AP.OutContext), AP.OutContext); | |
| HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); | |
| MCO = MCOperand::createExpr(Expr); | |
| break; | |
| } | |
| case MachineOperand::MO_MachineBasicBlock: { | |
| MCExpr const *Expr = MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), | |
| AP.OutContext); | |
| Expr = HexagonMCExpr::create(Expr, AP.OutContext); | |
| HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend); | |
| MCO = MCOperand::createExpr(Expr); | |
| break; | |
| } | |
| case MachineOperand::MO_GlobalAddress: | |
| MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP, MustExtend); | |
| break; | |
| case MachineOperand::MO_ExternalSymbol: | |
| MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), | |
| AP, MustExtend); | |
| break; | |
| case MachineOperand::MO_JumpTableIndex: | |
| MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, MustExtend); | |
| break; | |
| case MachineOperand::MO_ConstantPoolIndex: | |
| MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, MustExtend); | |
| break; | |
| case MachineOperand::MO_BlockAddress: | |
| MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP, | |
| MustExtend); | |
| break; | |
| } | |
| MCI->addOperand(MCO); | |
| } | |
| AP.HexagonProcessInstruction(*MCI, *MI); | |
| HexagonMCInstrInfo::extendIfNeeded(AP.OutContext, MCII, MCB, *MCI); | |
| MCB.addOperand(MCOperand::createInst(MCI)); | |
| } |