Mercurial > hg > CbC > CbC_llvm
comparison lib/Target/Lanai/LanaiAsmPrinter.cpp @ 120:1172e4bd9c6f
update 4.0.0
author | mir3636 |
---|---|
date | Fri, 25 Nov 2016 19:14:25 +0900 |
parents | |
children | c2174574ed3a |
comparison
equal
deleted
inserted
replaced
101:34baf5011add | 120:1172e4bd9c6f |
---|---|
1 //===-- LanaiAsmPrinter.cpp - Lanai LLVM assembly writer ------------------===// | |
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 a printer that converts from our internal representation | |
11 // of machine-dependent LLVM code to the Lanai assembly language. | |
12 // | |
13 //===----------------------------------------------------------------------===// | |
14 | |
15 #include "InstPrinter/LanaiInstPrinter.h" | |
16 #include "Lanai.h" | |
17 #include "LanaiInstrInfo.h" | |
18 #include "LanaiMCInstLower.h" | |
19 #include "LanaiTargetMachine.h" | |
20 #include "llvm/CodeGen/AsmPrinter.h" | |
21 #include "llvm/CodeGen/MachineConstantPool.h" | |
22 #include "llvm/CodeGen/MachineFunctionPass.h" | |
23 #include "llvm/CodeGen/MachineInstr.h" | |
24 #include "llvm/CodeGen/MachineModuleInfo.h" | |
25 #include "llvm/IR/Constants.h" | |
26 #include "llvm/IR/DerivedTypes.h" | |
27 #include "llvm/IR/Mangler.h" | |
28 #include "llvm/IR/Module.h" | |
29 #include "llvm/MC/MCAsmInfo.h" | |
30 #include "llvm/MC/MCInst.h" | |
31 #include "llvm/MC/MCInstBuilder.h" | |
32 #include "llvm/MC/MCStreamer.h" | |
33 #include "llvm/MC/MCSymbol.h" | |
34 #include "llvm/Support/TargetRegistry.h" | |
35 #include "llvm/Support/raw_ostream.h" | |
36 | |
37 #define DEBUG_TYPE "asm-printer" | |
38 | |
39 using namespace llvm; | |
40 | |
41 namespace { | |
42 class LanaiAsmPrinter : public AsmPrinter { | |
43 public: | |
44 explicit LanaiAsmPrinter(TargetMachine &TM, | |
45 std::unique_ptr<MCStreamer> Streamer) | |
46 : AsmPrinter(TM, std::move(Streamer)) {} | |
47 | |
48 StringRef getPassName() const override { return "Lanai Assembly Printer"; } | |
49 | |
50 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); | |
51 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | |
52 unsigned AsmVariant, const char *ExtraCode, | |
53 raw_ostream &O) override; | |
54 void EmitInstruction(const MachineInstr *MI) override; | |
55 bool isBlockOnlyReachableByFallthrough( | |
56 const MachineBasicBlock *MBB) const override; | |
57 | |
58 private: | |
59 void customEmitInstruction(const MachineInstr *MI); | |
60 void emitCallInstruction(const MachineInstr *MI); | |
61 }; | |
62 } // end of anonymous namespace | |
63 | |
64 void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, | |
65 raw_ostream &O) { | |
66 const MachineOperand &MO = MI->getOperand(OpNum); | |
67 | |
68 switch (MO.getType()) { | |
69 case MachineOperand::MO_Register: | |
70 O << LanaiInstPrinter::getRegisterName(MO.getReg()); | |
71 break; | |
72 | |
73 case MachineOperand::MO_Immediate: | |
74 O << MO.getImm(); | |
75 break; | |
76 | |
77 case MachineOperand::MO_MachineBasicBlock: | |
78 O << *MO.getMBB()->getSymbol(); | |
79 break; | |
80 | |
81 case MachineOperand::MO_GlobalAddress: | |
82 O << *getSymbol(MO.getGlobal()); | |
83 break; | |
84 | |
85 case MachineOperand::MO_BlockAddress: { | |
86 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); | |
87 O << BA->getName(); | |
88 break; | |
89 } | |
90 | |
91 case MachineOperand::MO_ExternalSymbol: | |
92 O << *GetExternalSymbolSymbol(MO.getSymbolName()); | |
93 break; | |
94 | |
95 case MachineOperand::MO_JumpTableIndex: | |
96 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' | |
97 << MO.getIndex(); | |
98 break; | |
99 | |
100 case MachineOperand::MO_ConstantPoolIndex: | |
101 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' | |
102 << MO.getIndex(); | |
103 return; | |
104 | |
105 default: | |
106 llvm_unreachable("<unknown operand type>"); | |
107 } | |
108 } | |
109 | |
110 // PrintAsmOperand - Print out an operand for an inline asm expression. | |
111 bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | |
112 unsigned /*AsmVariant*/, | |
113 const char *ExtraCode, raw_ostream &O) { | |
114 // Does this asm operand have a single letter operand modifier? | |
115 if (ExtraCode && ExtraCode[0]) { | |
116 if (ExtraCode[1]) | |
117 return true; // Unknown modifier. | |
118 | |
119 switch (ExtraCode[0]) { | |
120 // The highest-numbered register of a pair. | |
121 case 'H': { | |
122 if (OpNo == 0) | |
123 return true; | |
124 const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1); | |
125 if (!FlagsOP.isImm()) | |
126 return true; | |
127 unsigned Flags = FlagsOP.getImm(); | |
128 unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); | |
129 if (NumVals != 2) | |
130 return true; | |
131 unsigned RegOp = OpNo + 1; | |
132 if (RegOp >= MI->getNumOperands()) | |
133 return true; | |
134 const MachineOperand &MO = MI->getOperand(RegOp); | |
135 if (!MO.isReg()) | |
136 return true; | |
137 unsigned Reg = MO.getReg(); | |
138 O << LanaiInstPrinter::getRegisterName(Reg); | |
139 return false; | |
140 } | |
141 default: | |
142 return true; // Unknown modifier. | |
143 } | |
144 } | |
145 printOperand(MI, OpNo, O); | |
146 return false; | |
147 } | |
148 | |
149 //===----------------------------------------------------------------------===// | |
150 void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) { | |
151 assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) && | |
152 "Unsupported call function"); | |
153 | |
154 LanaiMCInstLower MCInstLowering(OutContext, *this); | |
155 MCSubtargetInfo STI = getSubtargetInfo(); | |
156 // Insert save rca instruction immediately before the call. | |
157 // TODO: We should generate a pc-relative mov instruction here instead | |
158 // of pc + 16 (should be mov .+16 %rca). | |
159 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO) | |
160 .addReg(Lanai::RCA) | |
161 .addReg(Lanai::PC) | |
162 .addImm(16), | |
163 STI); | |
164 | |
165 // Push rca onto the stack. | |
166 // st %rca, [--%sp] | |
167 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI) | |
168 .addReg(Lanai::RCA) | |
169 .addReg(Lanai::SP) | |
170 .addImm(-4) | |
171 .addImm(LPAC::makePreOp(LPAC::ADD)), | |
172 STI); | |
173 | |
174 // Lower the call instruction. | |
175 if (MI->getOpcode() == Lanai::CALL) { | |
176 MCInst TmpInst; | |
177 MCInstLowering.Lower(MI, TmpInst); | |
178 TmpInst.setOpcode(Lanai::BT); | |
179 OutStreamer->EmitInstruction(TmpInst, STI); | |
180 } else { | |
181 OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R) | |
182 .addReg(Lanai::PC) | |
183 .addReg(MI->getOperand(0).getReg()) | |
184 .addReg(Lanai::R0) | |
185 .addImm(LPCC::ICC_T), | |
186 STI); | |
187 } | |
188 } | |
189 | |
190 void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) { | |
191 LanaiMCInstLower MCInstLowering(OutContext, *this); | |
192 MCSubtargetInfo STI = getSubtargetInfo(); | |
193 MCInst TmpInst; | |
194 MCInstLowering.Lower(MI, TmpInst); | |
195 OutStreamer->EmitInstruction(TmpInst, STI); | |
196 } | |
197 | |
198 void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) { | |
199 MachineBasicBlock::const_instr_iterator I = MI->getIterator(); | |
200 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); | |
201 | |
202 do { | |
203 if (I->isCall()) { | |
204 emitCallInstruction(&*I); | |
205 continue; | |
206 } | |
207 | |
208 customEmitInstruction(&*I); | |
209 } while ((++I != E) && I->isInsideBundle()); | |
210 } | |
211 | |
212 // isBlockOnlyReachableByFallthough - Return true if the basic block has | |
213 // exactly one predecessor and the control transfer mechanism between | |
214 // the predecessor and this block is a fall-through. | |
215 // FIXME: could the overridden cases be handled in AnalyzeBranch? | |
216 bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough( | |
217 const MachineBasicBlock *MBB) const { | |
218 // The predecessor has to be immediately before this block. | |
219 const MachineBasicBlock *Pred = *MBB->pred_begin(); | |
220 | |
221 // If the predecessor is a switch statement, assume a jump table | |
222 // implementation, so it is not a fall through. | |
223 if (const BasicBlock *B = Pred->getBasicBlock()) | |
224 if (isa<SwitchInst>(B->getTerminator())) | |
225 return false; | |
226 | |
227 // Check default implementation | |
228 if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB)) | |
229 return false; | |
230 | |
231 // Otherwise, check the last instruction. | |
232 // Check if the last terminator is an unconditional branch. | |
233 MachineBasicBlock::const_iterator I = Pred->end(); | |
234 while (I != Pred->begin() && !(--I)->isTerminator()) { | |
235 } | |
236 | |
237 return !I->isBarrier(); | |
238 } | |
239 | |
240 // Force static initialization. | |
241 extern "C" void LLVMInitializeLanaiAsmPrinter() { | |
242 RegisterAsmPrinter<LanaiAsmPrinter> X(getTheLanaiTarget()); | |
243 } |