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