OLD | NEW |
---|---|
(Empty) | |
1 //===- subzero/src/llvm2ice.cpp - Driver for testing ----------------------===// | |
2 // | |
3 // The Subzero Code Generator | |
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 defines a driver that uses LLVM capabilities to parse a | |
11 // bitcode file and build the LLVM IR, and then convert the LLVM basic | |
12 // blocks, instructions, and operands into their Subzero equivalents. | |
13 // | |
14 //===----------------------------------------------------------------------===// | |
15 | |
16 #include "IceCfg.h" | |
17 #include "IceCfgNode.h" | |
18 #include "IceDefs.h" | |
19 #include "IceInst.h" | |
20 #include "IceOperand.h" | |
21 #include "IceTypes.h" | |
22 | |
23 #include "llvm/IR/Constant.h" | |
24 #include "llvm/IR/Constants.h" | |
25 #include "llvm/IR/DataLayout.h" | |
26 #include "llvm/IR/Instruction.h" | |
27 #include "llvm/IR/Instructions.h" | |
28 #include "llvm/IR/LLVMContext.h" | |
29 #include "llvm/IR/Module.h" | |
30 #include "llvm/IRReader/IRReader.h" | |
31 #include "llvm/Support/CommandLine.h" | |
32 #include "llvm/Support/ErrorHandling.h" | |
33 #include "llvm/Support/raw_os_ostream.h" | |
34 #include "llvm/Support/SourceMgr.h" | |
35 | |
36 #include <fstream> | |
37 #include <iostream> | |
38 | |
39 using namespace llvm; | |
40 | |
41 // Debugging helper | |
42 template <typename T> static std::string LLVMObjectAsString(const T *O) { | |
43 std::string Dump; | |
44 raw_string_ostream Stream(Dump); | |
45 O->print(Stream); | |
46 return Stream.str(); | |
47 } | |
48 | |
49 // Converter from LLVM to ICE. The entry point is the convertFunction method. | |
50 // | |
51 // Note: this currently assumes that the given IR was verified to be valid PNaCl | |
52 // bitcode: | |
53 // https://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi | |
54 // If not, all kinds of assertions may fire. | |
55 // | |
56 class LLVM2ICEConverter { | |
57 public: | |
58 LLVM2ICEConverter() : Cfg(NULL), CurrentNode(NULL) {} | |
59 | |
60 IceCfg *convertFunction(const Function *F) { | |
61 VarMap.clear(); | |
62 NodeMap.clear(); | |
63 Cfg = new IceCfg; | |
64 Cfg->setName(F->getName()); | |
65 Cfg->setReturnType(convertType(F->getReturnType())); | |
66 Cfg->setInternal(F->hasInternalLinkage()); | |
67 | |
68 // The initial definition/use of each arg is the entry node. | |
69 CurrentNode = mapBasicBlockToNode(&F->getEntryBlock()); | |
70 for (Function::const_arg_iterator ArgI = F->arg_begin(), | |
71 ArgE = F->arg_end(); | |
72 ArgI != ArgE; ++ArgI) { | |
73 Cfg->addArg(mapValueToIceVar(ArgI)); | |
74 } | |
75 | |
76 // Make an initial pass through the block list just to resolve the | |
77 // blocks in the original linearized order. Otherwise the ICE | |
78 // linearized order will be affected by branch targets in | |
79 // terminator instructions. | |
80 for (Function::const_iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; | |
81 ++BBI) { | |
82 mapBasicBlockToNode(BBI); | |
83 } | |
84 for (Function::const_iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; | |
85 ++BBI) { | |
86 CurrentNode = mapBasicBlockToNode(BBI); | |
87 convertBasicBlock(BBI); | |
88 } | |
89 Cfg->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock())); | |
90 Cfg->registerEdges(); | |
91 | |
92 return Cfg; | |
93 } | |
94 | |
95 private: | |
96 // LLVM values (instructions, etc.) are mapped directly to ICE variables. | |
97 // mapValueToIceVar has a version that forces an ICE type on the variable, | |
98 // and a version that just uses convertType on V. | |
99 IceVariable *mapValueToIceVar(const Value *V, IceType IceTy) { | |
100 if (IceTy == IceType_void) | |
101 return NULL; | |
102 if (VarMap.find(V) == VarMap.end()) { | |
103 assert(CurrentNode); | |
104 VarMap[V] = Cfg->makeVariable(IceTy, CurrentNode, V->getName()); | |
105 } | |
106 return VarMap[V]; | |
107 } | |
108 | |
109 IceVariable *mapValueToIceVar(const Value *V) { | |
110 return mapValueToIceVar(V, convertType(V->getType())); | |
111 } | |
112 | |
113 IceCfgNode *mapBasicBlockToNode(const BasicBlock *BB) { | |
114 if (NodeMap.find(BB) == NodeMap.end()) { | |
115 NodeMap[BB] = Cfg->makeNode(BB->getName()); | |
116 } | |
117 return NodeMap[BB]; | |
118 } | |
119 | |
120 IceType convertIntegerType(const IntegerType *IntTy) { | |
jvoung (off chromium)
2014/03/22 00:29:39
is this const?
Jim Stichnoth
2014/03/24 13:18:53
Done, also convertType() below.
| |
121 switch (IntTy->getBitWidth()) { | |
122 case 1: | |
123 return IceType_i1; | |
124 case 8: | |
125 return IceType_i8; | |
126 case 16: | |
127 return IceType_i16; | |
128 case 32: | |
129 return IceType_i32; | |
130 case 64: | |
131 return IceType_i64; | |
132 default: | |
133 report_fatal_error(std::string("Invalid PNaCl int type: ") + | |
134 LLVMObjectAsString(IntTy)); | |
135 return IceType_void; | |
136 } | |
137 } | |
138 | |
139 IceType convertType(const Type *Ty) { | |
140 switch (Ty->getTypeID()) { | |
141 case Type::VoidTyID: | |
142 return IceType_void; | |
143 case Type::IntegerTyID: | |
144 return convertIntegerType(cast<IntegerType>(Ty)); | |
145 case Type::FloatTyID: | |
146 return IceType_f32; | |
147 case Type::DoubleTyID: | |
148 return IceType_f64; | |
149 case Type::PointerTyID: { | |
150 const PointerType *PTy = cast<PointerType>(Ty); | |
151 return convertType(PTy->getElementType()); | |
jvoung (off chromium)
2014/03/28 16:17:07
Should this also return i32? Otherwise wouldn't it
jvoung (off chromium)
2014/03/28 23:21:53
ping?
Jim Stichnoth
2014/03/29 14:23:22
Sorry, done. This was left over from earlier repr
| |
152 } | |
153 case Type::FunctionTyID: | |
154 return IceType_i32; | |
jvoung (off chromium)
2014/03/22 00:29:39
This i32 is for function ptr, or function-but-not-
Jim Stichnoth
2014/03/24 13:18:53
Generally I was following https://developers.googl
Jim Stichnoth
2014/03/28 13:52:18
I looked into this some more. In addition to this
jvoung (off chromium)
2014/03/28 16:17:07
Okay seems fine to keep this the way it is then. I
Jim Stichnoth
2014/03/28 16:45:08
Done.
| |
155 default: | |
156 report_fatal_error(std::string("Invalid PNaCl type: ") + | |
157 LLVMObjectAsString(Ty)); | |
158 } | |
159 | |
160 llvm_unreachable("convertType"); | |
161 return IceType_void; | |
162 } | |
163 | |
164 // Given a LLVM instruction and an operand number, produce the IceOperand this | |
165 // refers to. If there's no such operand, return NULL. | |
166 IceOperand *convertOperand(const Instruction *Inst, unsigned OpNum) { | |
167 if (OpNum >= Inst->getNumOperands()) { | |
168 return NULL; | |
169 } | |
170 const Value *Op = Inst->getOperand(OpNum); | |
171 return convertValue(Op); | |
172 } | |
173 | |
174 IceOperand *convertValue(const Value *Op) { | |
175 if (const Constant *Const = dyn_cast<Constant>(Op)) { | |
176 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Const)) { | |
177 return Cfg->getConstantSym(convertType(GV->getType()), GV, 0, | |
178 GV->getName()); | |
179 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Const)) { | |
180 return Cfg->getConstantInt(convertIntegerType(CI->getType()), | |
181 CI->getZExtValue()); | |
182 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Const)) { | |
183 IceType Type = convertType(CFP->getType()); | |
184 if (Type == IceType_f32) | |
185 return Cfg->getConstantFloat(CFP->getValueAPF().convertToFloat()); | |
186 else if (Type == IceType_f64) | |
187 return Cfg->getConstantDouble(CFP->getValueAPF().convertToDouble()); | |
188 assert(0 && "Unexpected floating point type"); | |
189 return NULL; | |
190 } else { | |
191 assert(0 && "Unhandled constant type"); | |
192 return NULL; | |
193 } | |
194 } else { | |
195 return mapValueToIceVar(Op); | |
196 } | |
197 } | |
198 | |
199 // Note: this currently assumes a 1x1 mapping between LLVM IR and Ice | |
200 // instructions. | |
201 IceInst *convertInstruction(const Instruction *Inst) { | |
202 switch (Inst->getOpcode()) { | |
203 case Instruction::PHI: | |
204 return convertPHINodeInstruction(cast<PHINode>(Inst)); | |
205 case Instruction::Br: | |
206 return convertBrInstruction(cast<BranchInst>(Inst)); | |
207 case Instruction::Ret: | |
208 return convertRetInstruction(cast<ReturnInst>(Inst)); | |
209 case Instruction::IntToPtr: | |
210 return convertIntToPtrInstruction(cast<IntToPtrInst>(Inst)); | |
211 case Instruction::PtrToInt: | |
212 return convertPtrToIntInstruction(cast<PtrToIntInst>(Inst)); | |
213 case Instruction::ICmp: | |
214 return convertICmpInstruction(cast<ICmpInst>(Inst)); | |
215 case Instruction::FCmp: | |
216 return convertFCmpInstruction(cast<FCmpInst>(Inst)); | |
217 case Instruction::Select: | |
218 return convertSelectInstruction(cast<SelectInst>(Inst)); | |
219 case Instruction::Switch: | |
220 return convertSwitchInstruction(cast<SwitchInst>(Inst)); | |
221 case Instruction::Load: | |
222 return convertLoadInstruction(cast<LoadInst>(Inst)); | |
223 case Instruction::Store: | |
224 return convertStoreInstruction(cast<StoreInst>(Inst)); | |
225 case Instruction::ZExt: | |
226 return convertCastInstruction(cast<ZExtInst>(Inst), IceInstCast::Zext); | |
227 case Instruction::SExt: | |
228 return convertCastInstruction(cast<SExtInst>(Inst), IceInstCast::Sext); | |
229 case Instruction::Trunc: | |
230 return convertCastInstruction(cast<TruncInst>(Inst), IceInstCast::Trunc); | |
231 case Instruction::FPTrunc: | |
232 return convertCastInstruction(cast<FPTruncInst>(Inst), | |
233 IceInstCast::Fptrunc); | |
234 case Instruction::FPExt: | |
235 return convertCastInstruction(cast<FPExtInst>(Inst), IceInstCast::Fpext); | |
236 case Instruction::FPToSI: | |
237 return convertCastInstruction(cast<FPToSIInst>(Inst), | |
238 IceInstCast::Fptosi); | |
239 case Instruction::FPToUI: | |
240 return convertCastInstruction(cast<FPToUIInst>(Inst), | |
241 IceInstCast::Fptoui); | |
242 case Instruction::SIToFP: | |
243 return convertCastInstruction(cast<SIToFPInst>(Inst), | |
244 IceInstCast::Sitofp); | |
245 case Instruction::UIToFP: | |
246 return convertCastInstruction(cast<UIToFPInst>(Inst), | |
247 IceInstCast::Uitofp); | |
248 case Instruction::Add: | |
249 return convertArithInstruction(Inst, IceInstArithmetic::Add); | |
250 case Instruction::Sub: | |
251 return convertArithInstruction(Inst, IceInstArithmetic::Sub); | |
252 case Instruction::Mul: | |
253 return convertArithInstruction(Inst, IceInstArithmetic::Mul); | |
254 case Instruction::UDiv: | |
255 return convertArithInstruction(Inst, IceInstArithmetic::Udiv); | |
256 case Instruction::SDiv: | |
257 return convertArithInstruction(Inst, IceInstArithmetic::Sdiv); | |
258 case Instruction::URem: | |
259 return convertArithInstruction(Inst, IceInstArithmetic::Urem); | |
260 case Instruction::SRem: | |
261 return convertArithInstruction(Inst, IceInstArithmetic::Srem); | |
262 case Instruction::Shl: | |
263 return convertArithInstruction(Inst, IceInstArithmetic::Shl); | |
264 case Instruction::LShr: | |
265 return convertArithInstruction(Inst, IceInstArithmetic::Lshr); | |
266 case Instruction::AShr: | |
267 return convertArithInstruction(Inst, IceInstArithmetic::Ashr); | |
268 case Instruction::FAdd: | |
269 return convertArithInstruction(Inst, IceInstArithmetic::Fadd); | |
270 case Instruction::FSub: | |
271 return convertArithInstruction(Inst, IceInstArithmetic::Fsub); | |
272 case Instruction::FMul: | |
273 return convertArithInstruction(Inst, IceInstArithmetic::Fmul); | |
274 case Instruction::FDiv: | |
275 return convertArithInstruction(Inst, IceInstArithmetic::Fdiv); | |
276 case Instruction::FRem: | |
277 return convertArithInstruction(Inst, IceInstArithmetic::Frem); | |
278 case Instruction::And: | |
279 return convertArithInstruction(Inst, IceInstArithmetic::And); | |
280 case Instruction::Or: | |
281 return convertArithInstruction(Inst, IceInstArithmetic::Or); | |
282 case Instruction::Xor: | |
283 return convertArithInstruction(Inst, IceInstArithmetic::Xor); | |
284 case Instruction::Call: | |
285 return convertCallInstruction(cast<CallInst>(Inst)); | |
286 case Instruction::Alloca: | |
287 return convertAllocaInstruction(cast<AllocaInst>(Inst)); | |
288 default: | |
289 report_fatal_error(std::string("Invalid PNaCl instruction: ") + | |
290 LLVMObjectAsString(Inst)); | |
291 } | |
292 | |
293 llvm_unreachable("convertInstruction"); | |
294 return NULL; | |
295 } | |
296 | |
297 IceInst *convertLoadInstruction(const LoadInst *Inst) { | |
298 IceOperand *Src = convertOperand(Inst, 0); | |
299 IceVariable *Dest = mapValueToIceVar(Inst); | |
300 return IceInstLoad::create(Cfg, Dest, Src); | |
301 } | |
302 | |
303 IceInst *convertStoreInstruction(const StoreInst *Inst) { | |
304 IceOperand *Addr = convertOperand(Inst, 1); | |
305 IceOperand *Val = convertOperand(Inst, 0); | |
306 return IceInstStore::create(Cfg, Val, Addr); | |
307 } | |
308 | |
309 IceInst *convertArithInstruction(const Instruction *Inst, | |
310 IceInstArithmetic::OpKind Opcode) { | |
311 const BinaryOperator *BinOp = cast<BinaryOperator>(Inst); | |
312 IceOperand *Src0 = convertOperand(Inst, 0); | |
313 IceOperand *Src1 = convertOperand(Inst, 1); | |
314 IceVariable *Dest = mapValueToIceVar(BinOp); | |
315 return IceInstArithmetic::create(Cfg, Opcode, Dest, Src0, Src1); | |
316 } | |
317 | |
318 IceInst *convertPHINodeInstruction(const PHINode *Inst) { | |
319 unsigned NumValues = Inst->getNumIncomingValues(); | |
320 IceInstPhi *IcePhi = | |
321 IceInstPhi::create(Cfg, NumValues, mapValueToIceVar(Inst)); | |
322 for (unsigned N = 0, E = NumValues; N != E; ++N) { | |
323 IcePhi->addArgument(convertOperand(Inst, N), | |
324 mapBasicBlockToNode(Inst->getIncomingBlock(N))); | |
325 } | |
326 return IcePhi; | |
327 } | |
328 | |
329 IceInst *convertBrInstruction(const BranchInst *Inst) { | |
330 if (Inst->isConditional()) { | |
331 IceOperand *Src = convertOperand(Inst, 0); | |
332 BasicBlock *BBThen = Inst->getSuccessor(0); | |
333 BasicBlock *BBElse = Inst->getSuccessor(1); | |
334 IceCfgNode *NodeThen = mapBasicBlockToNode(BBThen); | |
335 IceCfgNode *NodeElse = mapBasicBlockToNode(BBElse); | |
336 return IceInstBr::create(Cfg, Src, NodeThen, NodeElse); | |
337 } else { | |
338 BasicBlock *BBSucc = Inst->getSuccessor(0); | |
339 return IceInstBr::create(Cfg, mapBasicBlockToNode(BBSucc)); | |
340 } | |
341 } | |
342 | |
343 IceInst *convertIntToPtrInstruction(const IntToPtrInst *Inst) { | |
344 IceOperand *Src = convertOperand(Inst, 0); | |
345 IceVariable *Dest = mapValueToIceVar(Inst, IceType_i32); | |
346 return IceInstAssign::create(Cfg, Dest, Src); | |
347 } | |
348 | |
349 IceInst *convertPtrToIntInstruction(const PtrToIntInst *Inst) { | |
350 IceOperand *Src = convertOperand(Inst, 0); | |
351 IceVariable *Dest = mapValueToIceVar(Inst); | |
352 return IceInstAssign::create(Cfg, Dest, Src); | |
353 } | |
354 | |
355 IceInst *convertRetInstruction(const ReturnInst *Inst) { | |
356 IceOperand *RetOperand = convertOperand(Inst, 0); | |
357 if (RetOperand) { | |
358 return IceInstRet::create(Cfg, RetOperand); | |
359 } else { | |
360 return IceInstRet::create(Cfg); | |
361 } | |
362 } | |
363 | |
364 IceInst *convertCastInstruction(const Instruction *Inst, | |
365 IceInstCast::OpKind CastKind) { | |
366 IceOperand *Src = convertOperand(Inst, 0); | |
367 IceVariable *Dest = mapValueToIceVar(Inst); | |
368 return IceInstCast::create(Cfg, CastKind, Dest, Src); | |
369 } | |
370 | |
371 IceInst *convertICmpInstruction(const ICmpInst *Inst) { | |
372 IceOperand *Src0 = convertOperand(Inst, 0); | |
373 IceOperand *Src1 = convertOperand(Inst, 1); | |
374 IceVariable *Dest = mapValueToIceVar(Inst); | |
375 | |
376 IceInstIcmp::ICond Cond; | |
377 switch (Inst->getPredicate()) { | |
378 default: | |
379 llvm_unreachable("ICmpInst predicate"); | |
380 case CmpInst::ICMP_EQ: | |
381 Cond = IceInstIcmp::Eq; | |
382 break; | |
383 case CmpInst::ICMP_NE: | |
384 Cond = IceInstIcmp::Ne; | |
385 break; | |
386 case CmpInst::ICMP_UGT: | |
387 Cond = IceInstIcmp::Ugt; | |
388 break; | |
389 case CmpInst::ICMP_UGE: | |
390 Cond = IceInstIcmp::Uge; | |
391 break; | |
392 case CmpInst::ICMP_ULT: | |
393 Cond = IceInstIcmp::Ult; | |
394 break; | |
395 case CmpInst::ICMP_ULE: | |
396 Cond = IceInstIcmp::Ule; | |
397 break; | |
398 case CmpInst::ICMP_SGT: | |
399 Cond = IceInstIcmp::Sgt; | |
400 break; | |
401 case CmpInst::ICMP_SGE: | |
402 Cond = IceInstIcmp::Sge; | |
403 break; | |
404 case CmpInst::ICMP_SLT: | |
405 Cond = IceInstIcmp::Slt; | |
406 break; | |
407 case CmpInst::ICMP_SLE: | |
408 Cond = IceInstIcmp::Sle; | |
409 break; | |
410 } | |
411 | |
412 return IceInstIcmp::create(Cfg, Cond, Dest, Src0, Src1); | |
413 } | |
414 | |
415 IceInst *convertFCmpInstruction(const FCmpInst *Inst) { | |
416 IceOperand *Src0 = convertOperand(Inst, 0); | |
417 IceOperand *Src1 = convertOperand(Inst, 1); | |
418 IceVariable *Dest = mapValueToIceVar(Inst); | |
419 | |
420 IceInstFcmp::FCond Cond; | |
421 switch (Inst->getPredicate()) { | |
422 | |
423 default: | |
424 llvm_unreachable("FCmpInst predicate"); | |
425 | |
426 case CmpInst::FCMP_FALSE: | |
427 Cond = IceInstFcmp::False; | |
428 break; | |
429 case CmpInst::FCMP_OEQ: | |
430 Cond = IceInstFcmp::Oeq; | |
431 break; | |
432 case CmpInst::FCMP_OGT: | |
433 Cond = IceInstFcmp::Ogt; | |
434 break; | |
435 case CmpInst::FCMP_OGE: | |
436 Cond = IceInstFcmp::Oge; | |
437 break; | |
438 case CmpInst::FCMP_OLT: | |
439 Cond = IceInstFcmp::Olt; | |
440 break; | |
441 case CmpInst::FCMP_OLE: | |
442 Cond = IceInstFcmp::Ole; | |
443 break; | |
444 case CmpInst::FCMP_ONE: | |
445 Cond = IceInstFcmp::One; | |
446 break; | |
447 case CmpInst::FCMP_ORD: | |
448 Cond = IceInstFcmp::Ord; | |
449 break; | |
450 case CmpInst::FCMP_UEQ: | |
451 Cond = IceInstFcmp::Ueq; | |
452 break; | |
453 case CmpInst::FCMP_UGT: | |
454 Cond = IceInstFcmp::Ugt; | |
455 break; | |
456 case CmpInst::FCMP_UGE: | |
457 Cond = IceInstFcmp::Uge; | |
458 break; | |
459 case CmpInst::FCMP_ULT: | |
460 Cond = IceInstFcmp::Ult; | |
461 break; | |
462 case CmpInst::FCMP_ULE: | |
463 Cond = IceInstFcmp::Ule; | |
464 break; | |
465 case CmpInst::FCMP_UNE: | |
466 Cond = IceInstFcmp::Une; | |
467 break; | |
468 case CmpInst::FCMP_UNO: | |
469 Cond = IceInstFcmp::Uno; | |
470 break; | |
471 case CmpInst::FCMP_TRUE: | |
472 Cond = IceInstFcmp::True; | |
473 break; | |
474 } | |
475 | |
476 return IceInstFcmp::create(Cfg, Cond, Dest, Src0, Src1); | |
477 } | |
478 | |
479 IceInst *convertSelectInstruction(const SelectInst *Inst) { | |
480 IceVariable *Dest = mapValueToIceVar(Inst); | |
481 IceOperand *Cond = convertValue(Inst->getCondition()); | |
482 IceOperand *Source1 = convertValue(Inst->getTrueValue()); | |
483 IceOperand *Source2 = convertValue(Inst->getFalseValue()); | |
484 return IceInstSelect::create(Cfg, Dest, Cond, Source1, Source2); | |
485 } | |
486 | |
487 IceInst *convertSwitchInstruction(const SwitchInst *Inst) { | |
488 IceOperand *Source = convertValue(Inst->getCondition()); | |
489 IceCfgNode *LabelDefault = mapBasicBlockToNode(Inst->getDefaultDest()); | |
490 unsigned NumCases = Inst->getNumCases(); | |
491 IceInstSwitch *Switch = | |
492 IceInstSwitch::create(Cfg, NumCases, Source, LabelDefault); | |
493 unsigned CurrentCase = 0; | |
494 for (SwitchInst::ConstCaseIt I = Inst->case_begin(), E = Inst->case_end(); | |
495 I != E; ++I, ++CurrentCase) { | |
496 uint64_t CaseValue = I.getCaseValue()->getZExtValue(); | |
497 IceCfgNode *CaseSuccessor = mapBasicBlockToNode(I.getCaseSuccessor()); | |
498 Switch->addBranch(CurrentCase, CaseValue, CaseSuccessor); | |
499 } | |
500 return Switch; | |
501 } | |
502 | |
503 IceInst *convertCallInstruction(const CallInst *Inst) { | |
504 IceVariable *Dest = mapValueToIceVar(Inst); | |
505 IceOperand *CallTarget = convertValue(Inst->getCalledValue()); | |
506 unsigned NumArgs = Inst->getNumArgOperands(); | |
507 IceInstCall *NewInst = | |
508 IceInstCall::create(Cfg, NumArgs, Dest, CallTarget, Inst->isTailCall()); | |
509 for (unsigned i = 0; i < NumArgs; ++i) { | |
510 NewInst->addArg(convertOperand(Inst, i)); | |
511 } | |
512 return NewInst; | |
513 } | |
514 | |
515 IceInst *convertAllocaInstruction(const AllocaInst *Inst) { | |
516 // PNaCl bitcode only contains allocas of byte-granular objects. | |
517 IceOperand *ByteCount = convertValue(Inst->getArraySize()); | |
518 uint32_t Align = Inst->getAlignment(); | |
519 IceVariable *Dest = mapValueToIceVar(Inst, IceType_i32); | |
520 | |
521 return IceInstAlloca::create(Cfg, ByteCount, Align, Dest); | |
522 } | |
523 | |
524 IceCfgNode *convertBasicBlock(const BasicBlock *BB) { | |
525 IceCfgNode *Node = mapBasicBlockToNode(BB); | |
526 for (BasicBlock::const_iterator II = BB->begin(), II_e = BB->end(); | |
527 II != II_e; ++II) { | |
528 IceInst *Inst = convertInstruction(II); | |
529 Node->appendInst(Inst); | |
530 } | |
531 return Node; | |
532 } | |
533 | |
534 private: | |
535 // Data | |
536 IceCfg *Cfg; | |
537 IceCfgNode *CurrentNode; | |
538 std::map<const Value *, IceVariable *> VarMap; | |
539 std::map<const BasicBlock *, IceCfgNode *> NodeMap; | |
540 }; | |
541 | |
542 static cl::list<IceVerbose> VerboseList( | |
543 "verbose", cl::CommaSeparated, | |
544 cl::desc("Verbose options (can be comma-separated):"), | |
545 cl::values( | |
546 clEnumValN(IceV_Instructions, "inst", "Print basic instructions"), | |
547 clEnumValN(IceV_Deleted, "del", "Include deleted instructions"), | |
548 clEnumValN(IceV_InstNumbers, "instnum", "Print instruction numbers"), | |
549 clEnumValN(IceV_Preds, "pred", "Show predecessors"), | |
550 clEnumValN(IceV_Succs, "succ", "Show successors"), | |
551 clEnumValN(IceV_Liveness, "live", "Liveness information"), | |
552 clEnumValN(IceV_RegManager, "rmgr", "Register manager status"), | |
553 clEnumValN(IceV_RegOrigins, "orig", "Physical register origins"), | |
554 clEnumValN(IceV_LinearScan, "regalloc", "Linear scan details"), | |
555 clEnumValN(IceV_Frame, "frame", "Stack frame layout details"), | |
556 clEnumValN(IceV_Timing, "time", "Pass timing details"), | |
557 clEnumValN(IceV_All, "all", "Use all verbose options"), | |
558 clEnumValN(IceV_None, "none", "No verbosity"), clEnumValEnd)); | |
559 static cl::opt<std::string> IRFilename(cl::Positional, cl::desc("<IR file>"), | |
560 cl::Required); | |
561 static cl::opt<std::string> OutputFilename("o", | |
562 cl::desc("Override output filename"), | |
563 cl::init("-"), | |
564 cl::value_desc("filename")); | |
565 static cl::opt<std::string> | |
566 TestPrefix("prefix", cl::desc("Prepend a prefix to symbol names for testing"), | |
567 cl::init(""), cl::value_desc("prefix")); | |
568 static cl::opt<bool> | |
569 DisableInternal("external", | |
570 cl::desc("Disable 'internal' linkage type for testing")); | |
571 static cl::opt<bool> | |
572 DisableTranslation("notranslate", cl::desc("Disable Subzero translation")); | |
573 | |
574 static cl::opt<bool> SubzeroTimingEnabled( | |
575 "timing", cl::desc("Enable breakdown timing of Subzero translation")); | |
576 | |
577 int main(int argc, char **argv) { | |
578 cl::ParseCommandLineOptions(argc, argv); | |
579 | |
580 // Parse the input LLVM IR file into a module. | |
581 SMDiagnostic Err; | |
582 Module *Mod; | |
583 | |
584 { | |
585 IceTimer T; | |
586 Mod = ParseIRFile(IRFilename, Err, getGlobalContext()); | |
587 | |
588 if (SubzeroTimingEnabled) { | |
589 std::cerr << "[Subzero timing] IR Parsing: " << T.getElapsedSec() | |
590 << " sec\n"; | |
591 } | |
592 } | |
593 | |
594 if (!Mod) { | |
595 Err.print(argv[0], errs()); | |
596 return 1; | |
597 } | |
598 | |
599 IceVerboseMask VerboseMask = IceV_None; | |
600 for (unsigned i = 0; i != VerboseList.size(); ++i) | |
601 VerboseMask |= VerboseList[i]; | |
602 | |
603 std::ofstream Ofs; | |
604 if (OutputFilename != "-") { | |
605 Ofs.open(OutputFilename.c_str(), std::ofstream::out); | |
606 } | |
607 raw_os_ostream *Os = | |
608 new raw_os_ostream(OutputFilename == "-" ? std::cout : Ofs); | |
609 Os->SetUnbuffered(); | |
610 | |
611 for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { | |
612 if (I->empty()) | |
613 continue; | |
614 LLVM2ICEConverter FunctionConverter; | |
615 | |
616 IceTimer TConvert; | |
617 IceCfg *Cfg = FunctionConverter.convertFunction(I); | |
618 if (DisableInternal) | |
619 Cfg->setInternal(false); | |
620 | |
621 if (SubzeroTimingEnabled) { | |
622 std::cerr << "[Subzero timing] Convert function " << Cfg->getName() | |
623 << ": " << TConvert.getElapsedSec() << " sec\n"; | |
624 } | |
625 | |
626 Cfg->setTestPrefix(TestPrefix); | |
627 Cfg->Str.Stream = Os; | |
628 Cfg->Str.setVerbose(VerboseMask); | |
629 if (DisableTranslation) { | |
630 Cfg->dump(); | |
631 } | |
632 } | |
633 | |
634 return 0; | |
635 } | |
OLD | NEW |