12d1f6d67SPete Couperus //===- ARCMCInstLower.cpp - ARC MachineInstr to MCInst ----------*- C++ -*-===//
22d1f6d67SPete Couperus //
32d1f6d67SPete Couperus //                     The LLVM Compiler Infrastructure
42d1f6d67SPete Couperus //
52d1f6d67SPete Couperus // This file is distributed under the University of Illinois Open Source
62d1f6d67SPete Couperus // License. See LICENSE.TXT for details.
72d1f6d67SPete Couperus //
82d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
92d1f6d67SPete Couperus ///
102d1f6d67SPete Couperus /// \file
11*5f8f34e4SAdrian Prantl /// This file contains code to lower ARC MachineInstrs to their
122d1f6d67SPete Couperus /// corresponding MCInst records.
132d1f6d67SPete Couperus ///
142d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
152d1f6d67SPete Couperus 
162d1f6d67SPete Couperus #include "ARCMCInstLower.h"
172d1f6d67SPete Couperus #include "llvm/CodeGen/AsmPrinter.h"
182d1f6d67SPete Couperus #include "llvm/CodeGen/MachineFunction.h"
192d1f6d67SPete Couperus #include "llvm/CodeGen/MachineInstr.h"
202d1f6d67SPete Couperus #include "llvm/CodeGen/MachineOperand.h"
212d1f6d67SPete Couperus #include "llvm/MC/MCContext.h"
222d1f6d67SPete Couperus #include "llvm/MC/MCExpr.h"
232d1f6d67SPete Couperus #include "llvm/MC/MCInst.h"
242d1f6d67SPete Couperus 
252d1f6d67SPete Couperus using namespace llvm;
262d1f6d67SPete Couperus 
272d1f6d67SPete Couperus ARCMCInstLower::ARCMCInstLower(MCContext *C, AsmPrinter &AsmPrinter)
282d1f6d67SPete Couperus     : Ctx(C), Printer(AsmPrinter) {}
292d1f6d67SPete Couperus 
302d1f6d67SPete Couperus MCOperand ARCMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
312d1f6d67SPete Couperus                                              MachineOperandType MOTy,
322d1f6d67SPete Couperus                                              unsigned Offset) const {
332d1f6d67SPete Couperus   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
342d1f6d67SPete Couperus   const MCSymbol *Symbol;
352d1f6d67SPete Couperus 
362d1f6d67SPete Couperus   switch (MOTy) {
372d1f6d67SPete Couperus   case MachineOperand::MO_MachineBasicBlock:
382d1f6d67SPete Couperus     Symbol = MO.getMBB()->getSymbol();
392d1f6d67SPete Couperus     break;
402d1f6d67SPete Couperus   case MachineOperand::MO_GlobalAddress:
412d1f6d67SPete Couperus     Symbol = Printer.getSymbol(MO.getGlobal());
422d1f6d67SPete Couperus     Offset += MO.getOffset();
432d1f6d67SPete Couperus     break;
442d1f6d67SPete Couperus   case MachineOperand::MO_BlockAddress:
452d1f6d67SPete Couperus     Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress());
462d1f6d67SPete Couperus     Offset += MO.getOffset();
472d1f6d67SPete Couperus     break;
482d1f6d67SPete Couperus   case MachineOperand::MO_ExternalSymbol:
492d1f6d67SPete Couperus     Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName());
502d1f6d67SPete Couperus     Offset += MO.getOffset();
512d1f6d67SPete Couperus     break;
522d1f6d67SPete Couperus   case MachineOperand::MO_JumpTableIndex:
532d1f6d67SPete Couperus     Symbol = Printer.GetJTISymbol(MO.getIndex());
542d1f6d67SPete Couperus     break;
552d1f6d67SPete Couperus   case MachineOperand::MO_ConstantPoolIndex:
562d1f6d67SPete Couperus     Symbol = Printer.GetCPISymbol(MO.getIndex());
572d1f6d67SPete Couperus     Offset += MO.getOffset();
582d1f6d67SPete Couperus     break;
592d1f6d67SPete Couperus   default:
602d1f6d67SPete Couperus     llvm_unreachable("<unknown operand type>");
612d1f6d67SPete Couperus   }
622d1f6d67SPete Couperus 
632d1f6d67SPete Couperus   assert(Symbol && "Symbol creation failed.\n");
642d1f6d67SPete Couperus   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
652d1f6d67SPete Couperus 
662d1f6d67SPete Couperus   if (!Offset)
672d1f6d67SPete Couperus     return MCOperand::createExpr(MCSym);
682d1f6d67SPete Couperus 
692d1f6d67SPete Couperus   // Assume offset is never negative.
702d1f6d67SPete Couperus   assert(Offset > 0);
712d1f6d67SPete Couperus 
722d1f6d67SPete Couperus   const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx);
732d1f6d67SPete Couperus   const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx);
742d1f6d67SPete Couperus   return MCOperand::createExpr(Add);
752d1f6d67SPete Couperus }
762d1f6d67SPete Couperus 
772d1f6d67SPete Couperus MCOperand ARCMCInstLower::LowerOperand(const MachineOperand &MO,
782d1f6d67SPete Couperus                                        unsigned Offset) const {
792d1f6d67SPete Couperus   MachineOperandType MOTy = MO.getType();
802d1f6d67SPete Couperus 
812d1f6d67SPete Couperus   switch (MOTy) {
822d1f6d67SPete Couperus   default:
832d1f6d67SPete Couperus     llvm_unreachable("unknown operand type");
842d1f6d67SPete Couperus   case MachineOperand::MO_Register:
852d1f6d67SPete Couperus     // Ignore all implicit register operands.
862d1f6d67SPete Couperus     if (MO.isImplicit())
872d1f6d67SPete Couperus       break;
882d1f6d67SPete Couperus     return MCOperand::createReg(MO.getReg());
892d1f6d67SPete Couperus   case MachineOperand::MO_Immediate:
902d1f6d67SPete Couperus     return MCOperand::createImm(MO.getImm() + Offset);
912d1f6d67SPete Couperus   case MachineOperand::MO_MachineBasicBlock:
922d1f6d67SPete Couperus   case MachineOperand::MO_GlobalAddress:
932d1f6d67SPete Couperus   case MachineOperand::MO_ExternalSymbol:
942d1f6d67SPete Couperus   case MachineOperand::MO_JumpTableIndex:
952d1f6d67SPete Couperus   case MachineOperand::MO_ConstantPoolIndex:
962d1f6d67SPete Couperus   case MachineOperand::MO_BlockAddress:
972d1f6d67SPete Couperus     return LowerSymbolOperand(MO, MOTy, Offset);
982d1f6d67SPete Couperus   case MachineOperand::MO_RegisterMask:
992d1f6d67SPete Couperus     break;
1002d1f6d67SPete Couperus   }
1012d1f6d67SPete Couperus 
1022d1f6d67SPete Couperus   return {};
1032d1f6d67SPete Couperus }
1042d1f6d67SPete Couperus 
1052d1f6d67SPete Couperus void ARCMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
1062d1f6d67SPete Couperus   OutMI.setOpcode(MI->getOpcode());
1072d1f6d67SPete Couperus 
1082d1f6d67SPete Couperus   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
1092d1f6d67SPete Couperus     const MachineOperand &MO = MI->getOperand(i);
1102d1f6d67SPete Couperus     MCOperand MCOp = LowerOperand(MO);
1112d1f6d67SPete Couperus 
1122d1f6d67SPete Couperus     if (MCOp.isValid())
1132d1f6d67SPete Couperus       OutMI.addOperand(MCOp);
1142d1f6d67SPete Couperus   }
1152d1f6d67SPete Couperus }
116