llvm-stress.cpp revision fdc309cc4e95778d7615f3829917c4fe42086e1e
1//===-- llvm-stress.cpp - Print the size of each object section ------------===// 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 program is a utility that generates random .ll files to stress-test 11// different components in LLVM. 12// 13//===----------------------------------------------------------------------===// 14#include "llvm/LLVMContext.h" 15#include "llvm/Module.h" 16#include "llvm/PassManager.h" 17#include "llvm/Constants.h" 18#include "llvm/Instruction.h" 19#include "llvm/CallGraphSCCPass.h" 20#include "llvm/Assembly/PrintModulePass.h" 21#include "llvm/Analysis/Verifier.h" 22#include "llvm/Support/PassNameParser.h" 23#include "llvm/Support/Debug.h" 24#include "llvm/Support/ManagedStatic.h" 25#include "llvm/Support/PluginLoader.h" 26#include "llvm/Support/PrettyStackTrace.h" 27#include "llvm/Support/ToolOutputFile.h" 28#include <memory> 29#include <sstream> 30#include <set> 31#include <vector> 32#include <algorithm> 33using namespace llvm; 34 35static cl::opt<unsigned> SeedCL("seed", 36 cl::desc("Seed used for randomness"), cl::init(0)); 37static cl::opt<unsigned> SizeCL("size", 38 cl::desc("The estimated size of the generated function (# of instrs)"), 39 cl::init(100)); 40static cl::opt<std::string> 41OutputFilename("o", cl::desc("Override output filename"), 42 cl::value_desc("filename")); 43 44/// A utility class to provide a pseudo-random number generator which is 45/// the same across all platforms. This is somewhat close to the libc 46/// implementation. Note: This is not a cryptographically secure pseudorandom 47/// number generator. 48class Random { 49public: 50 /// C'tor 51 Random(unsigned _seed):Seed(_seed) {} 52 /// Return the next random value. 53 unsigned Rand() { 54 unsigned Val = Seed + 0x000b07a1; 55 Seed = (Val * 0x3c7c0ac1); 56 // Only lowest 19 bits are random-ish. 57 return Seed & 0x7ffff; 58 } 59 60private: 61 unsigned Seed; 62}; 63 64/// Generate an empty function with a default argument list. 65Function *GenEmptyFunction(Module *M) { 66 // Type Definitions 67 std::vector<Type*> ArgsTy; 68 // Define a few arguments 69 LLVMContext &Context = M->getContext(); 70 ArgsTy.push_back(PointerType::get(IntegerType::getInt8Ty(Context), 0)); 71 ArgsTy.push_back(PointerType::get(IntegerType::getInt32Ty(Context), 0)); 72 ArgsTy.push_back(PointerType::get(IntegerType::getInt64Ty(Context), 0)); 73 ArgsTy.push_back(IntegerType::getInt32Ty(Context)); 74 ArgsTy.push_back(IntegerType::getInt64Ty(Context)); 75 ArgsTy.push_back(IntegerType::getInt8Ty(Context)); 76 77 FunctionType *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, 0); 78 // Pick a unique name to describe the input parameters 79 std::stringstream ss; 80 ss<<"autogen_SD"<<SeedCL; 81 Function *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, 82 ss.str(), M); 83 84 Func->setCallingConv(CallingConv::C); 85 return Func; 86} 87 88/// A base class, implementing utilities needed for 89/// modifying and adding new random instructions. 90struct Modifier { 91 /// Used to store the randomly generated values. 92 typedef std::vector<Value*> PieceTable; 93 94public: 95 /// C'tor 96 Modifier(BasicBlock *_BB, PieceTable *PT, Random *R): 97 BB(_BB),PT(PT),Ran(R),Context(BB->getContext()) {}; 98 /// Add a new instruction. 99 virtual void Act() = 0; 100 /// Add N new instructions, 101 virtual void ActN(unsigned n) { 102 for (unsigned i=0; i<n; ++i) 103 Act(); 104 } 105 106protected: 107 /// Return a random value from the list of known values. 108 Value *getRandomVal() { 109 assert(PT->size()); 110 return PT->at(Ran->Rand() % PT->size()); 111 } 112 113 /// Return a random value with a known type. 114 Value *getRandomValue(Type *Tp) { 115 unsigned index = Ran->Rand(); 116 for (unsigned i=0; i<PT->size(); ++i) { 117 Value *V = PT->at((index + i) % PT->size()); 118 if (V->getType() == Tp) 119 return V; 120 } 121 122 // If the requested type was not found, generate a constant value. 123 if (Tp->isIntegerTy()) { 124 if (Ran->Rand() & 1) 125 return ConstantInt::getAllOnesValue(Tp); 126 return ConstantInt::getNullValue(Tp); 127 } else if (Tp->isFloatingPointTy()) { 128 if (Ran->Rand() & 1) 129 return ConstantFP::getAllOnesValue(Tp); 130 return ConstantFP::getNullValue(Tp); 131 } 132 133 // TODO: return values for vector types. 134 return UndefValue::get(Tp); 135 } 136 137 /// Return a random value of any pointer type. 138 Value *getRandomPointerValue() { 139 unsigned index = Ran->Rand(); 140 for (unsigned i=0; i<PT->size(); ++i) { 141 Value *V = PT->at((index + i) % PT->size()); 142 if (V->getType()->isPointerTy()) 143 return V; 144 } 145 return UndefValue::get(pickPointerType()); 146 } 147 148 /// Return a random value of any vector type. 149 Value *getRandomVectorValue() { 150 unsigned index = Ran->Rand(); 151 for (unsigned i=0; i<PT->size(); ++i) { 152 Value *V = PT->at((index + i) % PT->size()); 153 if (V->getType()->isVectorTy()) 154 return V; 155 } 156 return UndefValue::get(pickVectorType()); 157 } 158 159 /// Pick a random type. 160 Type *pickType() { 161 return (Ran->Rand() & 1 ? pickVectorType() : pickScalarType()); 162 } 163 164 /// Pick a random pointer type. 165 Type *pickPointerType() { 166 Type *Ty = pickType(); 167 return PointerType::get(Ty, 0); 168 } 169 170 /// Pick a random vector type. 171 Type *pickVectorType(unsigned len = (unsigned)-1) { 172 Type *Ty = pickScalarType(); 173 // Pick a random vector width in the range 2**0 to 2**4. 174 // by adding two randoms we are generating a normal-like distribution 175 // around 2**3. 176 unsigned width = 1<<((Ran->Rand() % 3) + (Ran->Rand() % 3)); 177 if (len != (unsigned)-1) 178 width = len; 179 return VectorType::get(Ty, width); 180 } 181 182 /// Pick a random scalar type. 183 Type *pickScalarType() { 184 switch (Ran->Rand() % 15) { 185 case 0: return Type::getInt1Ty(Context); 186 case 1: return Type::getInt8Ty(Context); 187 case 2: return Type::getInt16Ty(Context); 188 case 3: case 4: 189 case 5: return Type::getFloatTy(Context); 190 case 6: case 7: 191 case 8: return Type::getDoubleTy(Context); 192 case 9: case 10: 193 case 11: return Type::getInt32Ty(Context); 194 case 12: case 13: 195 case 14: return Type::getInt64Ty(Context); 196 } 197 llvm_unreachable("Invalid scalar value"); 198 } 199 200 /// Basic block to populate 201 BasicBlock *BB; 202 /// Value table 203 PieceTable *PT; 204 /// Random number generator 205 Random *Ran; 206 /// Context 207 LLVMContext &Context; 208}; 209 210struct LoadModifier: public Modifier { 211 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}; 212 virtual void Act() { 213 // Try to use predefined pointers. If non exist, use undef pointer value; 214 Value *Ptr = getRandomPointerValue(); 215 Value *V = new LoadInst(Ptr, "L", BB->getTerminator()); 216 PT->push_back(V); 217 } 218}; 219 220struct StoreModifier: public Modifier { 221 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 222 virtual void Act() { 223 // Try to use predefined pointers. If non exist, use undef pointer value; 224 Value *Ptr = getRandomPointerValue(); 225 Type *Tp = Ptr->getType(); 226 Value *Val = getRandomValue(Tp->getContainedType(0)); 227 228 // Do not store vectors of i1s because they are unsupported 229 //by the codegen. 230 if (Tp->isVectorTy() && Tp->getScalarSizeInBits() == 1) 231 return; 232 233 new StoreInst(Val, Ptr, BB->getTerminator()); 234 } 235}; 236 237struct BinModifier: public Modifier { 238 BinModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 239 240 virtual void Act() { 241 Value *Val0 = getRandomVal(); 242 Value *Val1 = getRandomValue(Val0->getType()); 243 244 // Don't handle pointer types. 245 if (Val0->getType()->isPointerTy() || 246 Val1->getType()->isPointerTy()) 247 return; 248 249 // Don't handle i1 types. 250 if (Val0->getType()->getScalarSizeInBits() == 1) 251 return; 252 253 254 bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy(); 255 Instruction* Term = BB->getTerminator(); 256 unsigned R = Ran->Rand() % (isFloat ? 7 : 13); 257 Instruction::BinaryOps Op; 258 259 switch (R) { 260 default: llvm_unreachable("Invalid BinOp"); 261 case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; } 262 case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; } 263 case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; } 264 case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; } 265 case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; } 266 case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; } 267 case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; } 268 case 7: {Op = Instruction::Shl; break; } 269 case 8: {Op = Instruction::LShr; break; } 270 case 9: {Op = Instruction::AShr; break; } 271 case 10:{Op = Instruction::And; break; } 272 case 11:{Op = Instruction::Or; break; } 273 case 12:{Op = Instruction::Xor; break; } 274 } 275 276 PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term)); 277 } 278}; 279 280/// Generate constant values. 281struct ConstModifier: public Modifier { 282 ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 283 virtual void Act() { 284 Type *Ty = pickType(); 285 286 if (Ty->isVectorTy()) { 287 switch (Ran->Rand() % 2) { 288 case 0: if (Ty->getScalarType()->isIntegerTy()) 289 return PT->push_back(ConstantVector::getAllOnesValue(Ty)); 290 case 1: if (Ty->getScalarType()->isIntegerTy()) 291 return PT->push_back(ConstantVector::getNullValue(Ty)); 292 } 293 } 294 295 if (Ty->isFloatingPointTy()) { 296 if (Ran->Rand() & 1) 297 return PT->push_back(ConstantFP::getNullValue(Ty)); 298 return PT->push_back(ConstantFP::get(Ty, 299 static_cast<double>(1)/Ran->Rand())); 300 } 301 302 if (Ty->isIntegerTy()) { 303 switch (Ran->Rand() % 7) { 304 case 0: if (Ty->isIntegerTy()) 305 return PT->push_back(ConstantInt::get(Ty, 306 APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits()))); 307 case 1: if (Ty->isIntegerTy()) 308 return PT->push_back(ConstantInt::get(Ty, 309 APInt::getNullValue(Ty->getPrimitiveSizeInBits()))); 310 case 2: case 3: case 4: case 5: 311 case 6: if (Ty->isIntegerTy()) 312 PT->push_back(ConstantInt::get(Ty, Ran->Rand())); 313 } 314 } 315 316 } 317}; 318 319struct AllocaModifier: public Modifier { 320 AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R){} 321 322 virtual void Act() { 323 Type *Tp = pickType(); 324 PT->push_back(new AllocaInst(Tp, "A", BB->getFirstNonPHI())); 325 } 326}; 327 328struct ExtractElementModifier: public Modifier { 329 ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R): 330 Modifier(BB, PT, R) {} 331 332 virtual void Act() { 333 Value *Val0 = getRandomVectorValue(); 334 Value *V = ExtractElementInst::Create(Val0, 335 ConstantInt::get(Type::getInt32Ty(BB->getContext()), 336 Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), 337 "E", BB->getTerminator()); 338 return PT->push_back(V); 339 } 340}; 341 342struct ShuffModifier: public Modifier { 343 ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 344 virtual void Act() { 345 346 Value *Val0 = getRandomVectorValue(); 347 Value *Val1 = getRandomValue(Val0->getType()); 348 349 unsigned Width = cast<VectorType>(Val0->getType())->getNumElements(); 350 std::vector<Constant*> Idxs; 351 352 Type *I32 = Type::getInt32Ty(BB->getContext()); 353 for (unsigned i=0; i<Width; ++i) { 354 Constant *CI = ConstantInt::get(I32, Ran->Rand() % (Width*2)); 355 // Pick some undef values. 356 if (!(Ran->Rand() % 5)) 357 CI = UndefValue::get(I32); 358 Idxs.push_back(CI); 359 } 360 361 Constant *Mask = ConstantVector::get(Idxs); 362 363 Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff", 364 BB->getTerminator()); 365 PT->push_back(V); 366 } 367}; 368 369struct InsertElementModifier: public Modifier { 370 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R): 371 Modifier(BB, PT, R) {} 372 373 virtual void Act() { 374 Value *Val0 = getRandomVectorValue(); 375 Value *Val1 = getRandomValue(Val0->getType()->getScalarType()); 376 377 Value *V = InsertElementInst::Create(Val0, Val1, 378 ConstantInt::get(Type::getInt32Ty(BB->getContext()), 379 Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), 380 "I", BB->getTerminator()); 381 return PT->push_back(V); 382 } 383 384}; 385 386struct CastModifier: public Modifier { 387 CastModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 388 virtual void Act() { 389 390 Value *V = getRandomVal(); 391 Type *VTy = V->getType(); 392 Type *DestTy = pickScalarType(); 393 394 // Handle vector casts vectors. 395 if (VTy->isVectorTy()) { 396 VectorType *VecTy = cast<VectorType>(VTy); 397 DestTy = pickVectorType(VecTy->getNumElements()); 398 } 399 400 // no need to casr. 401 if (VTy == DestTy) return; 402 403 // Pointers: 404 if (VTy->isPointerTy()) { 405 if (!DestTy->isPointerTy()) 406 DestTy = PointerType::get(DestTy, 0); 407 return PT->push_back( 408 new BitCastInst(V, DestTy, "PC", BB->getTerminator())); 409 } 410 411 // Generate lots of bitcasts. 412 if ((Ran->Rand() & 1) && 413 VTy->getPrimitiveSizeInBits() == DestTy->getPrimitiveSizeInBits()) { 414 return PT->push_back( 415 new BitCastInst(V, DestTy, "BC", BB->getTerminator())); 416 } 417 418 // Both types are integers: 419 if (VTy->getScalarType()->isIntegerTy() && 420 DestTy->getScalarType()->isIntegerTy()) { 421 if (VTy->getScalarType()->getPrimitiveSizeInBits() > 422 DestTy->getScalarType()->getPrimitiveSizeInBits()) { 423 return PT->push_back( 424 new TruncInst(V, DestTy, "Tr", BB->getTerminator())); 425 } else { 426 if (Ran->Rand() & 1) 427 return PT->push_back( 428 new ZExtInst(V, DestTy, "ZE", BB->getTerminator())); 429 return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator())); 430 } 431 } 432 433 // Fp to int. 434 if (VTy->getScalarType()->isFloatingPointTy() && 435 DestTy->getScalarType()->isIntegerTy()) { 436 if (Ran->Rand() & 1) 437 return PT->push_back( 438 new FPToSIInst(V, DestTy, "FC", BB->getTerminator())); 439 return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator())); 440 } 441 442 // Int to fp. 443 if (VTy->getScalarType()->isIntegerTy() && 444 DestTy->getScalarType()->isFloatingPointTy()) { 445 if (Ran->Rand() & 1) 446 return PT->push_back( 447 new SIToFPInst(V, DestTy, "FC", BB->getTerminator())); 448 return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator())); 449 450 } 451 452 // Both floats. 453 if (VTy->getScalarType()->isFloatingPointTy() && 454 DestTy->getScalarType()->isFloatingPointTy()) { 455 if (VTy->getScalarType()->getPrimitiveSizeInBits() > 456 DestTy->getScalarType()->getPrimitiveSizeInBits()) { 457 return PT->push_back( 458 new FPTruncInst(V, DestTy, "Tr", BB->getTerminator())); 459 } else { 460 return PT->push_back( 461 new FPExtInst(V, DestTy, "ZE", BB->getTerminator())); 462 } 463 } 464 } 465 466}; 467 468struct SelectModifier: public Modifier { 469 SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R): 470 Modifier(BB, PT, R) {} 471 472 virtual void Act() { 473 // Try a bunch of different select configuration until a valid one is found. 474 Value *Val0 = getRandomVal(); 475 Value *Val1 = getRandomValue(Val0->getType()); 476 477 Type *CondTy = Type::getInt1Ty(Context); 478 479 // If the value type is a vector, and we allow vector select, then in 50% 480 // of the cases generate a vector select. 481 if (Val0->getType()->isVectorTy() && (Ran->Rand() % 1)) { 482 unsigned NumElem = cast<VectorType>(Val0->getType())->getNumElements(); 483 CondTy = VectorType::get(CondTy, NumElem); 484 } 485 486 Value *Cond = getRandomValue(CondTy); 487 Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator()); 488 return PT->push_back(V); 489 } 490}; 491 492 493struct CmpModifier: public Modifier { 494 CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 495 virtual void Act() { 496 497 Value *Val0 = getRandomVal(); 498 Value *Val1 = getRandomValue(Val0->getType()); 499 500 if (Val0->getType()->isPointerTy()) return; 501 bool fp = Val0->getType()->getScalarType()->isFloatingPointTy(); 502 503 int op; 504 if (fp) { 505 op = Ran->Rand() % 506 (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) + 507 CmpInst::FIRST_FCMP_PREDICATE; 508 } else { 509 op = Ran->Rand() % 510 (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) + 511 CmpInst::FIRST_ICMP_PREDICATE; 512 } 513 514 Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp, 515 op, Val0, Val1, "Cmp", BB->getTerminator()); 516 return PT->push_back(V); 517 } 518}; 519 520void FillFunction(Function *F) { 521 // Create a legal entry block. 522 BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F); 523 ReturnInst::Create(F->getContext(), BB); 524 525 // Create the value table. 526 Modifier::PieceTable PT; 527 // Pick an initial seed value 528 Random R(SeedCL); 529 530 // Consider arguments as legal values. 531 for (Function::arg_iterator it = F->arg_begin(), e = F->arg_end(); 532 it != e; ++it) 533 PT.push_back(it); 534 535 // List of modifiers which add new random instructions. 536 std::vector<Modifier*> Modifiers; 537 std::auto_ptr<Modifier> LM(new LoadModifier(BB, &PT, &R)); 538 std::auto_ptr<Modifier> SM(new StoreModifier(BB, &PT, &R)); 539 std::auto_ptr<Modifier> EE(new ExtractElementModifier(BB, &PT, &R)); 540 std::auto_ptr<Modifier> SHM(new ShuffModifier(BB, &PT, &R)); 541 std::auto_ptr<Modifier> IE(new InsertElementModifier(BB, &PT, &R)); 542 std::auto_ptr<Modifier> BM(new BinModifier(BB, &PT, &R)); 543 std::auto_ptr<Modifier> CM(new CastModifier(BB, &PT, &R)); 544 std::auto_ptr<Modifier> SLM(new SelectModifier(BB, &PT, &R)); 545 std::auto_ptr<Modifier> PM(new CmpModifier(BB, &PT, &R)); 546 Modifiers.push_back(LM.get()); 547 Modifiers.push_back(SM.get()); 548 Modifiers.push_back(EE.get()); 549 Modifiers.push_back(SHM.get()); 550 Modifiers.push_back(IE.get()); 551 Modifiers.push_back(BM.get()); 552 Modifiers.push_back(CM.get()); 553 Modifiers.push_back(SLM.get()); 554 Modifiers.push_back(PM.get()); 555 556 // Generate the random instructions 557 AllocaModifier AM(BB, &PT, &R); AM.ActN(5); // Throw in a few allocas 558 ConstModifier COM(BB, &PT, &R); COM.ActN(40); // Throw in a few constants 559 560 for (unsigned i=0; i< SizeCL / Modifiers.size(); ++i) 561 for (std::vector<Modifier*>::iterator it = Modifiers.begin(), 562 e = Modifiers.end(); it != e; ++it) { 563 (*it)->Act(); 564 } 565 566 SM->ActN(5); // Throw in a few stores. 567} 568 569void IntroduceControlFlow(Function *F) { 570 std::set<Instruction*> BoolInst; 571 for (BasicBlock::iterator it = F->begin()->begin(), 572 e = F->begin()->end(); it != e; ++it) { 573 if (it->getType() == IntegerType::getInt1Ty(F->getContext())) 574 BoolInst.insert(it); 575 } 576 577 for (std::set<Instruction*>::iterator it = BoolInst.begin(), 578 e = BoolInst.end(); it != e; ++it) { 579 Instruction *Instr = *it; 580 BasicBlock *Curr = Instr->getParent(); 581 BasicBlock::iterator Loc= Instr; 582 BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF"); 583 Instr->moveBefore(Curr->getTerminator()); 584 if (Curr != &F->getEntryBlock()) { 585 BranchInst::Create(Curr, Next, Instr, Curr->getTerminator()); 586 Curr->getTerminator()->eraseFromParent(); 587 } 588 } 589} 590 591int main(int argc, char **argv) { 592 // Init LLVM, call llvm_shutdown() on exit, parse args, etc. 593 llvm::PrettyStackTraceProgram X(argc, argv); 594 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); 595 llvm_shutdown_obj Y; 596 597 std::auto_ptr<Module> M(new Module("/tmp/autogen.bc", getGlobalContext())); 598 Function *F = GenEmptyFunction(M.get()); 599 FillFunction(F); 600 IntroduceControlFlow(F); 601 602 // Figure out what stream we are supposed to write to... 603 OwningPtr<tool_output_file> Out; 604 // Default to standard output. 605 if (OutputFilename.empty()) 606 OutputFilename = "-"; 607 608 std::string ErrorInfo; 609 Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, 610 raw_fd_ostream::F_Binary)); 611 if (!ErrorInfo.empty()) { 612 errs() << ErrorInfo << '\n'; 613 return 1; 614 } 615 616 PassManager Passes; 617 Passes.add(createVerifierPass()); 618 Passes.add(createPrintModulePass(&Out->os())); 619 Passes.run(*M.get()); 620 Out->keep(); 621 622 return 0; 623} 624