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