1*5f613dfdSUlrich Weigand //===-- SystemZMCInstLower.cpp - Lower MachineInstr to MCInst -------------===//
2*5f613dfdSUlrich Weigand //
3*5f613dfdSUlrich Weigand //                     The LLVM Compiler Infrastructure
4*5f613dfdSUlrich Weigand //
5*5f613dfdSUlrich Weigand // This file is distributed under the University of Illinois Open Source
6*5f613dfdSUlrich Weigand // License. See LICENSE.TXT for details.
7*5f613dfdSUlrich Weigand //
8*5f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
9*5f613dfdSUlrich Weigand 
10*5f613dfdSUlrich Weigand #include "SystemZMCInstLower.h"
11*5f613dfdSUlrich Weigand #include "SystemZAsmPrinter.h"
12*5f613dfdSUlrich Weigand #include "llvm/MC/MCExpr.h"
13*5f613dfdSUlrich Weigand #include "llvm/MC/MCStreamer.h"
14*5f613dfdSUlrich Weigand #include "llvm/Target/Mangler.h"
15*5f613dfdSUlrich Weigand 
16*5f613dfdSUlrich Weigand using namespace llvm;
17*5f613dfdSUlrich Weigand 
18*5f613dfdSUlrich Weigand // Where relaxable pairs of reloc-generating instructions exist,
19*5f613dfdSUlrich Weigand // we tend to use the longest form by default, since that produces
20*5f613dfdSUlrich Weigand // correct assembly in cases where no relaxation is performed.
21*5f613dfdSUlrich Weigand // If Opcode is one such instruction, return the opcode for the
22*5f613dfdSUlrich Weigand // shortest possible form instead, otherwise return Opcode itself.
23*5f613dfdSUlrich Weigand static unsigned getShortenedInstr(unsigned Opcode) {
24*5f613dfdSUlrich Weigand   switch (Opcode) {
25*5f613dfdSUlrich Weigand   case SystemZ::BRCL:  return SystemZ::BRC;
26*5f613dfdSUlrich Weigand   case SystemZ::JG:    return SystemZ::J;
27*5f613dfdSUlrich Weigand   case SystemZ::BRASL: return SystemZ::BRAS;
28*5f613dfdSUlrich Weigand   }
29*5f613dfdSUlrich Weigand   return Opcode;
30*5f613dfdSUlrich Weigand }
31*5f613dfdSUlrich Weigand 
32*5f613dfdSUlrich Weigand // Return the VK_* enumeration for MachineOperand target flags Flags.
33*5f613dfdSUlrich Weigand static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) {
34*5f613dfdSUlrich Weigand   switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) {
35*5f613dfdSUlrich Weigand     case 0:
36*5f613dfdSUlrich Weigand       return MCSymbolRefExpr::VK_None;
37*5f613dfdSUlrich Weigand     case SystemZII::MO_GOT:
38*5f613dfdSUlrich Weigand       return MCSymbolRefExpr::VK_GOT;
39*5f613dfdSUlrich Weigand   }
40*5f613dfdSUlrich Weigand   llvm_unreachable("Unrecognised MO_ACCESS_MODEL");
41*5f613dfdSUlrich Weigand }
42*5f613dfdSUlrich Weigand 
43*5f613dfdSUlrich Weigand SystemZMCInstLower::SystemZMCInstLower(Mangler *mang, MCContext &ctx,
44*5f613dfdSUlrich Weigand                                        SystemZAsmPrinter &asmprinter)
45*5f613dfdSUlrich Weigand   : Mang(mang), Ctx(ctx), AsmPrinter(asmprinter) {}
46*5f613dfdSUlrich Weigand 
47*5f613dfdSUlrich Weigand MCOperand SystemZMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
48*5f613dfdSUlrich Weigand                                                  const MCSymbol *Symbol,
49*5f613dfdSUlrich Weigand                                                  int64_t Offset) const {
50*5f613dfdSUlrich Weigand   MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags());
51*5f613dfdSUlrich Weigand   const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx);
52*5f613dfdSUlrich Weigand   if (Offset) {
53*5f613dfdSUlrich Weigand     const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
54*5f613dfdSUlrich Weigand     Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
55*5f613dfdSUlrich Weigand   }
56*5f613dfdSUlrich Weigand   return MCOperand::CreateExpr(Expr);
57*5f613dfdSUlrich Weigand }
58*5f613dfdSUlrich Weigand 
59*5f613dfdSUlrich Weigand MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
60*5f613dfdSUlrich Weigand   switch (MO.getType()) {
61*5f613dfdSUlrich Weigand   default:
62*5f613dfdSUlrich Weigand     llvm_unreachable("unknown operand type");
63*5f613dfdSUlrich Weigand 
64*5f613dfdSUlrich Weigand   case MachineOperand::MO_Register:
65*5f613dfdSUlrich Weigand     // Ignore all implicit register operands.
66*5f613dfdSUlrich Weigand     if (MO.isImplicit())
67*5f613dfdSUlrich Weigand       return MCOperand();
68*5f613dfdSUlrich Weigand     return MCOperand::CreateReg(MO.getReg());
69*5f613dfdSUlrich Weigand 
70*5f613dfdSUlrich Weigand   case MachineOperand::MO_Immediate:
71*5f613dfdSUlrich Weigand     return MCOperand::CreateImm(MO.getImm());
72*5f613dfdSUlrich Weigand 
73*5f613dfdSUlrich Weigand   case MachineOperand::MO_MachineBasicBlock:
74*5f613dfdSUlrich Weigand     return lowerSymbolOperand(MO, MO.getMBB()->getSymbol(),
75*5f613dfdSUlrich Weigand                               /* MO has no offset field */0);
76*5f613dfdSUlrich Weigand 
77*5f613dfdSUlrich Weigand   case MachineOperand::MO_GlobalAddress:
78*5f613dfdSUlrich Weigand     return lowerSymbolOperand(MO, Mang->getSymbol(MO.getGlobal()),
79*5f613dfdSUlrich Weigand                               MO.getOffset());
80*5f613dfdSUlrich Weigand 
81*5f613dfdSUlrich Weigand   case MachineOperand::MO_ExternalSymbol: {
82*5f613dfdSUlrich Weigand     StringRef Name = MO.getSymbolName();
83*5f613dfdSUlrich Weigand     return lowerSymbolOperand(MO, AsmPrinter.GetExternalSymbolSymbol(Name),
84*5f613dfdSUlrich Weigand                               MO.getOffset());
85*5f613dfdSUlrich Weigand   }
86*5f613dfdSUlrich Weigand 
87*5f613dfdSUlrich Weigand   case MachineOperand::MO_JumpTableIndex:
88*5f613dfdSUlrich Weigand     return lowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()),
89*5f613dfdSUlrich Weigand                               /* MO has no offset field */0);
90*5f613dfdSUlrich Weigand 
91*5f613dfdSUlrich Weigand   case MachineOperand::MO_ConstantPoolIndex:
92*5f613dfdSUlrich Weigand     return lowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()),
93*5f613dfdSUlrich Weigand                               MO.getOffset());
94*5f613dfdSUlrich Weigand 
95*5f613dfdSUlrich Weigand   case MachineOperand::MO_BlockAddress: {
96*5f613dfdSUlrich Weigand     const BlockAddress *BA = MO.getBlockAddress();
97*5f613dfdSUlrich Weigand     return lowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol(BA),
98*5f613dfdSUlrich Weigand                               MO.getOffset());
99*5f613dfdSUlrich Weigand   }
100*5f613dfdSUlrich Weigand   }
101*5f613dfdSUlrich Weigand }
102*5f613dfdSUlrich Weigand 
103*5f613dfdSUlrich Weigand void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
104*5f613dfdSUlrich Weigand   unsigned Opcode = MI->getOpcode();
105*5f613dfdSUlrich Weigand   // When emitting binary code, start with the shortest form of an instruction
106*5f613dfdSUlrich Weigand   // and then relax it where necessary.
107*5f613dfdSUlrich Weigand   if (!AsmPrinter.OutStreamer.hasRawTextSupport())
108*5f613dfdSUlrich Weigand     Opcode = getShortenedInstr(Opcode);
109*5f613dfdSUlrich Weigand   OutMI.setOpcode(Opcode);
110*5f613dfdSUlrich Weigand   for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
111*5f613dfdSUlrich Weigand     const MachineOperand &MO = MI->getOperand(I);
112*5f613dfdSUlrich Weigand     MCOperand MCOp = lowerOperand(MO);
113*5f613dfdSUlrich Weigand     if (MCOp.isValid())
114*5f613dfdSUlrich Weigand       OutMI.addOperand(MCOp);
115*5f613dfdSUlrich Weigand   }
116*5f613dfdSUlrich Weigand }
117