1284c1978SDimitry Andric //===-- SystemZMCInstLower.cpp - Lower MachineInstr to MCInst -------------===//
2284c1978SDimitry Andric //
3284c1978SDimitry Andric //                     The LLVM Compiler Infrastructure
4284c1978SDimitry Andric //
5284c1978SDimitry Andric // This file is distributed under the University of Illinois Open Source
6284c1978SDimitry Andric // License. See LICENSE.TXT for details.
7284c1978SDimitry Andric //
8284c1978SDimitry Andric //===----------------------------------------------------------------------===//
9284c1978SDimitry Andric 
10284c1978SDimitry Andric #include "SystemZMCInstLower.h"
11284c1978SDimitry Andric #include "SystemZAsmPrinter.h"
1291bc56edSDimitry Andric #include "llvm/IR/Mangler.h"
13284c1978SDimitry Andric #include "llvm/MC/MCExpr.h"
14ff0cc061SDimitry Andric #include "llvm/MC/MCInst.h"
15284c1978SDimitry Andric #include "llvm/MC/MCStreamer.h"
16284c1978SDimitry Andric 
17284c1978SDimitry Andric using namespace llvm;
18284c1978SDimitry Andric 
19284c1978SDimitry Andric // Return the VK_* enumeration for MachineOperand target flags Flags.
getVariantKind(unsigned Flags)20284c1978SDimitry Andric static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) {
21284c1978SDimitry Andric   switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) {
22284c1978SDimitry Andric     case 0:
23284c1978SDimitry Andric       return MCSymbolRefExpr::VK_None;
24284c1978SDimitry Andric     case SystemZII::MO_GOT:
25284c1978SDimitry Andric       return MCSymbolRefExpr::VK_GOT;
26ff0cc061SDimitry Andric     case SystemZII::MO_INDNTPOFF:
27ff0cc061SDimitry Andric       return MCSymbolRefExpr::VK_INDNTPOFF;
28284c1978SDimitry Andric   }
29284c1978SDimitry Andric   llvm_unreachable("Unrecognised MO_ACCESS_MODEL");
30284c1978SDimitry Andric }
31284c1978SDimitry Andric 
SystemZMCInstLower(MCContext & ctx,SystemZAsmPrinter & asmprinter)32f785676fSDimitry Andric SystemZMCInstLower::SystemZMCInstLower(MCContext &ctx,
33284c1978SDimitry Andric                                        SystemZAsmPrinter &asmprinter)
34f785676fSDimitry Andric   : Ctx(ctx), AsmPrinter(asmprinter) {}
35284c1978SDimitry Andric 
36f785676fSDimitry Andric const MCExpr *
getExpr(const MachineOperand & MO,MCSymbolRefExpr::VariantKind Kind) const37f785676fSDimitry Andric SystemZMCInstLower::getExpr(const MachineOperand &MO,
38f785676fSDimitry Andric                             MCSymbolRefExpr::VariantKind Kind) const {
39f785676fSDimitry Andric   const MCSymbol *Symbol;
40f785676fSDimitry Andric   bool HasOffset = true;
41f785676fSDimitry Andric   switch (MO.getType()) {
42f785676fSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
43f785676fSDimitry Andric     Symbol = MO.getMBB()->getSymbol();
44f785676fSDimitry Andric     HasOffset = false;
45f785676fSDimitry Andric     break;
46f785676fSDimitry Andric 
47f785676fSDimitry Andric   case MachineOperand::MO_GlobalAddress:
48f785676fSDimitry Andric     Symbol = AsmPrinter.getSymbol(MO.getGlobal());
49f785676fSDimitry Andric     break;
50f785676fSDimitry Andric 
51f785676fSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
52f785676fSDimitry Andric     Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
53f785676fSDimitry Andric     break;
54f785676fSDimitry Andric 
55f785676fSDimitry Andric   case MachineOperand::MO_JumpTableIndex:
56f785676fSDimitry Andric     Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
57f785676fSDimitry Andric     HasOffset = false;
58f785676fSDimitry Andric     break;
59f785676fSDimitry Andric 
60f785676fSDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
61f785676fSDimitry Andric     Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
62f785676fSDimitry Andric     break;
63f785676fSDimitry Andric 
64f785676fSDimitry Andric   case MachineOperand::MO_BlockAddress:
65f785676fSDimitry Andric     Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
66f785676fSDimitry Andric     break;
67f785676fSDimitry Andric 
68f785676fSDimitry Andric   default:
69f785676fSDimitry Andric     llvm_unreachable("unknown operand type");
70f785676fSDimitry Andric   }
71*97bc6c73SDimitry Andric   const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, Ctx);
72f785676fSDimitry Andric   if (HasOffset)
73f785676fSDimitry Andric     if (int64_t Offset = MO.getOffset()) {
74*97bc6c73SDimitry Andric       const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
75*97bc6c73SDimitry Andric       Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
76284c1978SDimitry Andric     }
77f785676fSDimitry Andric   return Expr;
78284c1978SDimitry Andric }
79284c1978SDimitry Andric 
lowerOperand(const MachineOperand & MO) const80284c1978SDimitry Andric MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
81284c1978SDimitry Andric   switch (MO.getType()) {
82284c1978SDimitry Andric   case MachineOperand::MO_Register:
83ff0cc061SDimitry Andric     return MCOperand::createReg(MO.getReg());
84284c1978SDimitry Andric 
85284c1978SDimitry Andric   case MachineOperand::MO_Immediate:
86ff0cc061SDimitry Andric     return MCOperand::createImm(MO.getImm());
87284c1978SDimitry Andric 
88f785676fSDimitry Andric   default: {
89f785676fSDimitry Andric     MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags());
90ff0cc061SDimitry Andric     return MCOperand::createExpr(getExpr(MO, Kind));
91284c1978SDimitry Andric   }
92284c1978SDimitry Andric   }
93284c1978SDimitry Andric }
94284c1978SDimitry Andric 
lower(const MachineInstr * MI,MCInst & OutMI) const95284c1978SDimitry Andric void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
96f785676fSDimitry Andric   OutMI.setOpcode(MI->getOpcode());
97284c1978SDimitry Andric   for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
98284c1978SDimitry Andric     const MachineOperand &MO = MI->getOperand(I);
99f785676fSDimitry Andric     // Ignore all implicit register operands.
100f785676fSDimitry Andric     if (!MO.isReg() || !MO.isImplicit())
101f785676fSDimitry Andric       OutMI.addOperand(lowerOperand(MO));
102284c1978SDimitry Andric   }
103284c1978SDimitry Andric }
104