Change XCoreAsmPrinter to lower MachineInstrs to MCInsts before emission.
[oota-llvm.git] / lib / Target / XCore / XCoreMCInstLower.cpp
1 //===-- XCoreMCInstLower.cpp - Convert XCore 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 // This file contains code to lower XCore MachineInstrs to their corresponding
11 // MCInst records.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "XCoreMCInstLower.h"
15 #include "llvm/CodeGen/AsmPrinter.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineInstr.h"
18 #include "llvm/CodeGen/MachineOperand.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/Target/Mangler.h"
23
24 using namespace llvm;
25
26 XCoreMCInstLower::XCoreMCInstLower(class AsmPrinter &asmprinter)
27 : Printer(asmprinter) {}
28
29 void XCoreMCInstLower::Initialize(Mangler *M, MCContext *C) {
30   Mang = M;
31   Ctx = C;
32 }
33
34 MCOperand XCoreMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
35                                                MachineOperandType MOTy,
36                                                unsigned Offset) const {
37   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
38   const MCSymbol *Symbol;
39
40   switch (MOTy) {
41     case MachineOperand::MO_MachineBasicBlock:
42       Symbol = MO.getMBB()->getSymbol();
43       break;
44     case MachineOperand::MO_GlobalAddress:
45       Symbol = Mang->getSymbol(MO.getGlobal());
46       Offset += MO.getOffset();
47       break;
48     case MachineOperand::MO_BlockAddress:
49       Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress());
50       Offset += MO.getOffset();
51       break;
52     case MachineOperand::MO_ExternalSymbol:
53       Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName());
54       Offset += MO.getOffset();
55       break;
56     case MachineOperand::MO_JumpTableIndex:
57       Symbol = Printer.GetJTISymbol(MO.getIndex());
58       break;
59     case MachineOperand::MO_ConstantPoolIndex:
60       Symbol = Printer.GetCPISymbol(MO.getIndex());
61       Offset += MO.getOffset();
62       break;
63     default:
64       llvm_unreachable("<unknown operand type>");
65   }
66
67   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, *Ctx);
68
69   if (!Offset)
70     return MCOperand::CreateExpr(MCSym);
71
72   // Assume offset is never negative.
73   assert(Offset > 0);
74
75   const MCConstantExpr *OffsetExpr =  MCConstantExpr::Create(Offset, *Ctx);
76   const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx);
77   return MCOperand::CreateExpr(Add);
78 }
79
80 MCOperand XCoreMCInstLower::LowerOperand(const MachineOperand &MO,
81                                          unsigned offset) const {
82   MachineOperandType MOTy = MO.getType();
83
84   switch (MOTy) {
85     default: llvm_unreachable("unknown operand type");
86     case MachineOperand::MO_Register:
87       // Ignore all implicit register operands.
88       if (MO.isImplicit()) break;
89       return MCOperand::CreateReg(MO.getReg());
90     case MachineOperand::MO_Immediate:
91       return MCOperand::CreateImm(MO.getImm() + offset);
92     case MachineOperand::MO_MachineBasicBlock:
93     case MachineOperand::MO_GlobalAddress:
94     case MachineOperand::MO_ExternalSymbol:
95     case MachineOperand::MO_JumpTableIndex:
96     case MachineOperand::MO_ConstantPoolIndex:
97     case MachineOperand::MO_BlockAddress:
98       return LowerSymbolOperand(MO, MOTy, offset);
99     case MachineOperand::MO_RegisterMask:
100       break;
101   }
102
103   return MCOperand();
104 }
105
106 void XCoreMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
107   OutMI.setOpcode(MI->getOpcode());
108
109   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
110     const MachineOperand &MO = MI->getOperand(i);
111     MCOperand MCOp = LowerOperand(MO);
112
113     if (MCOp.isValid())
114       OutMI.addOperand(MCOp);
115   }
116 }