|  | //===- ARCMCInstLower.cpp - ARC MachineInstr to MCInst ----------*- C++ -*-===// | 
|  | // | 
|  | // 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 | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// This file contains code to lower ARC MachineInstrs to their | 
|  | /// corresponding MCInst records. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "ARCMCInstLower.h" | 
|  | #include "llvm/CodeGen/AsmPrinter.h" | 
|  | #include "llvm/CodeGen/MachineFunction.h" | 
|  | #include "llvm/CodeGen/MachineInstr.h" | 
|  | #include "llvm/CodeGen/MachineOperand.h" | 
|  | #include "llvm/MC/MCContext.h" | 
|  | #include "llvm/MC/MCExpr.h" | 
|  | #include "llvm/MC/MCInst.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | ARCMCInstLower::ARCMCInstLower(MCContext *C, AsmPrinter &AsmPrinter) | 
|  | : Ctx(C), Printer(AsmPrinter) {} | 
|  |  | 
|  | MCOperand ARCMCInstLower::LowerSymbolOperand(const MachineOperand &MO, | 
|  | MachineOperandType MOTy, | 
|  | unsigned Offset) const { | 
|  | MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; | 
|  | const MCSymbol *Symbol; | 
|  |  | 
|  | switch (MOTy) { | 
|  | case MachineOperand::MO_MachineBasicBlock: | 
|  | Symbol = MO.getMBB()->getSymbol(); | 
|  | break; | 
|  | case MachineOperand::MO_GlobalAddress: | 
|  | Symbol = Printer.getSymbol(MO.getGlobal()); | 
|  | Offset += MO.getOffset(); | 
|  | break; | 
|  | case MachineOperand::MO_BlockAddress: | 
|  | Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress()); | 
|  | Offset += MO.getOffset(); | 
|  | break; | 
|  | case MachineOperand::MO_ExternalSymbol: | 
|  | Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName()); | 
|  | Offset += MO.getOffset(); | 
|  | break; | 
|  | case MachineOperand::MO_JumpTableIndex: | 
|  | Symbol = Printer.GetJTISymbol(MO.getIndex()); | 
|  | break; | 
|  | case MachineOperand::MO_ConstantPoolIndex: | 
|  | Symbol = Printer.GetCPISymbol(MO.getIndex()); | 
|  | Offset += MO.getOffset(); | 
|  | break; | 
|  | default: | 
|  | llvm_unreachable("<unknown operand type>"); | 
|  | } | 
|  |  | 
|  | assert(Symbol && "Symbol creation failed.\n"); | 
|  | const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); | 
|  |  | 
|  | if (!Offset) | 
|  | return MCOperand::createExpr(MCSym); | 
|  |  | 
|  | // Assume offset is never negative. | 
|  | assert(Offset > 0); | 
|  |  | 
|  | const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx); | 
|  | const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx); | 
|  | return MCOperand::createExpr(Add); | 
|  | } | 
|  |  | 
|  | MCOperand ARCMCInstLower::LowerOperand(const MachineOperand &MO, | 
|  | unsigned Offset) const { | 
|  | MachineOperandType MOTy = MO.getType(); | 
|  |  | 
|  | switch (MOTy) { | 
|  | default: | 
|  | llvm_unreachable("unknown operand type"); | 
|  | case MachineOperand::MO_Register: | 
|  | // Ignore all implicit register operands. | 
|  | if (MO.isImplicit()) | 
|  | break; | 
|  | return MCOperand::createReg(MO.getReg()); | 
|  | case MachineOperand::MO_Immediate: | 
|  | return MCOperand::createImm(MO.getImm() + Offset); | 
|  | case MachineOperand::MO_MachineBasicBlock: | 
|  | case MachineOperand::MO_GlobalAddress: | 
|  | case MachineOperand::MO_ExternalSymbol: | 
|  | case MachineOperand::MO_JumpTableIndex: | 
|  | case MachineOperand::MO_ConstantPoolIndex: | 
|  | case MachineOperand::MO_BlockAddress: | 
|  | return LowerSymbolOperand(MO, MOTy, Offset); | 
|  | case MachineOperand::MO_RegisterMask: | 
|  | break; | 
|  | } | 
|  |  | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | void ARCMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { | 
|  | OutMI.setOpcode(MI->getOpcode()); | 
|  |  | 
|  | for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { | 
|  | const MachineOperand &MO = MI->getOperand(i); | 
|  | MCOperand MCOp = LowerOperand(MO); | 
|  |  | 
|  | if (MCOp.isValid()) | 
|  | OutMI.addOperand(MCOp); | 
|  | } | 
|  | } |