10b57cec5SDimitry Andric //===- ARCMCInstLower.cpp - ARC MachineInstr to MCInst ----------*- C++ -*-===//
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 /// \file
100b57cec5SDimitry Andric /// This file contains code to lower ARC MachineInstrs to their
110b57cec5SDimitry Andric /// corresponding MCInst records.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "ARCMCInstLower.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric
ARCMCInstLower(MCContext * C,AsmPrinter & AsmPrinter)260b57cec5SDimitry Andric ARCMCInstLower::ARCMCInstLower(MCContext *C, AsmPrinter &AsmPrinter)
270b57cec5SDimitry Andric : Ctx(C), Printer(AsmPrinter) {}
280b57cec5SDimitry Andric
LowerSymbolOperand(const MachineOperand & MO,MachineOperandType MOTy,unsigned Offset) const290b57cec5SDimitry Andric MCOperand ARCMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
300b57cec5SDimitry Andric MachineOperandType MOTy,
310b57cec5SDimitry Andric unsigned Offset) const {
320b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
330b57cec5SDimitry Andric const MCSymbol *Symbol;
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric switch (MOTy) {
360b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
370b57cec5SDimitry Andric Symbol = MO.getMBB()->getSymbol();
380b57cec5SDimitry Andric break;
390b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress:
400b57cec5SDimitry Andric Symbol = Printer.getSymbol(MO.getGlobal());
410b57cec5SDimitry Andric Offset += MO.getOffset();
420b57cec5SDimitry Andric break;
430b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress:
440b57cec5SDimitry Andric Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress());
450b57cec5SDimitry Andric Offset += MO.getOffset();
460b57cec5SDimitry Andric break;
470b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol:
480b57cec5SDimitry Andric Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName());
490b57cec5SDimitry Andric Offset += MO.getOffset();
500b57cec5SDimitry Andric break;
510b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex:
520b57cec5SDimitry Andric Symbol = Printer.GetJTISymbol(MO.getIndex());
530b57cec5SDimitry Andric break;
540b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
550b57cec5SDimitry Andric Symbol = Printer.GetCPISymbol(MO.getIndex());
560b57cec5SDimitry Andric Offset += MO.getOffset();
570b57cec5SDimitry Andric break;
580b57cec5SDimitry Andric default:
590b57cec5SDimitry Andric llvm_unreachable("<unknown operand type>");
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric assert(Symbol && "Symbol creation failed.\n");
630b57cec5SDimitry Andric const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric if (!Offset)
660b57cec5SDimitry Andric return MCOperand::createExpr(MCSym);
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric // Assume offset is never negative.
690b57cec5SDimitry Andric assert(Offset > 0);
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx);
720b57cec5SDimitry Andric const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx);
730b57cec5SDimitry Andric return MCOperand::createExpr(Add);
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
LowerOperand(const MachineOperand & MO,unsigned Offset) const760b57cec5SDimitry Andric MCOperand ARCMCInstLower::LowerOperand(const MachineOperand &MO,
770b57cec5SDimitry Andric unsigned Offset) const {
780b57cec5SDimitry Andric MachineOperandType MOTy = MO.getType();
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric switch (MOTy) {
810b57cec5SDimitry Andric default:
820b57cec5SDimitry Andric llvm_unreachable("unknown operand type");
830b57cec5SDimitry Andric case MachineOperand::MO_Register:
840b57cec5SDimitry Andric // Ignore all implicit register operands.
850b57cec5SDimitry Andric if (MO.isImplicit())
860b57cec5SDimitry Andric break;
870b57cec5SDimitry Andric return MCOperand::createReg(MO.getReg());
880b57cec5SDimitry Andric case MachineOperand::MO_Immediate:
890b57cec5SDimitry Andric return MCOperand::createImm(MO.getImm() + Offset);
900b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
910b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress:
920b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol:
930b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex:
940b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
950b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress:
960b57cec5SDimitry Andric return LowerSymbolOperand(MO, MOTy, Offset);
970b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask:
980b57cec5SDimitry Andric break;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric return {};
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
Lower(const MachineInstr * MI,MCInst & OutMI) const1040b57cec5SDimitry Andric void ARCMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
1050b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode());
1060b57cec5SDimitry Andric
107*4824e7fdSDimitry Andric for (const MachineOperand &MO : MI->operands()) {
1080b57cec5SDimitry Andric MCOperand MCOp = LowerOperand(MO);
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric if (MCOp.isValid())
1110b57cec5SDimitry Andric OutMI.addOperand(MCOp);
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric }
114