Path: blob/main/contrib/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
35260 views
//===- llvm-stress.cpp - Generate random LL files to stress-test LLVM -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This program is a utility that generates random .ll files to stress-test9// different components in LLVM.10//11//===----------------------------------------------------------------------===//1213#include "llvm/ADT/APFloat.h"14#include "llvm/ADT/APInt.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/ADT/Twine.h"19#include "llvm/IR/BasicBlock.h"20#include "llvm/IR/CallingConv.h"21#include "llvm/IR/Constants.h"22#include "llvm/IR/DataLayout.h"23#include "llvm/IR/DerivedTypes.h"24#include "llvm/IR/Function.h"25#include "llvm/IR/GlobalValue.h"26#include "llvm/IR/InstrTypes.h"27#include "llvm/IR/Instruction.h"28#include "llvm/IR/Instructions.h"29#include "llvm/IR/LLVMContext.h"30#include "llvm/IR/Module.h"31#include "llvm/IR/Type.h"32#include "llvm/IR/Value.h"33#include "llvm/IR/Verifier.h"34#include "llvm/Support/Casting.h"35#include "llvm/Support/CommandLine.h"36#include "llvm/Support/ErrorHandling.h"37#include "llvm/Support/FileSystem.h"38#include "llvm/Support/InitLLVM.h"39#include "llvm/Support/ToolOutputFile.h"40#include "llvm/Support/WithColor.h"41#include "llvm/Support/raw_ostream.h"42#include <algorithm>43#include <cassert>44#include <cstddef>45#include <cstdint>46#include <memory>47#include <string>48#include <system_error>49#include <vector>5051namespace llvm {5253static cl::OptionCategory StressCategory("Stress Options");5455static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"),56cl::init(0), cl::cat(StressCategory));5758static cl::opt<unsigned> SizeCL(59"size",60cl::desc("The estimated size of the generated function (# of instrs)"),61cl::init(100), cl::cat(StressCategory));6263static cl::opt<std::string> OutputFilename("o",64cl::desc("Override output filename"),65cl::value_desc("filename"),66cl::cat(StressCategory));6768static cl::list<StringRef> AdditionalScalarTypes(69"types", cl::CommaSeparated,70cl::desc("Additional IR scalar types "71"(always includes i1, i8, i16, i32, i64, float and double)"));7273static cl::opt<bool> EnableScalableVectors(74"enable-scalable-vectors",75cl::desc("Generate IR involving scalable vector types"),76cl::init(false), cl::cat(StressCategory));777879namespace {8081/// A utility class to provide a pseudo-random number generator which is82/// the same across all platforms. This is somewhat close to the libc83/// implementation. Note: This is not a cryptographically secure pseudorandom84/// number generator.85class Random {86public:87/// C'tor88Random(unsigned _seed):Seed(_seed) {}8990/// Return a random integer, up to a91/// maximum of 2**19 - 1.92uint32_t Rand() {93uint32_t Val = Seed + 0x000b07a1;94Seed = (Val * 0x3c7c0ac1);95// Only lowest 19 bits are random-ish.96return Seed & 0x7ffff;97}9899/// Return a random 64 bit integer.100uint64_t Rand64() {101uint64_t Val = Rand() & 0xffff;102Val |= uint64_t(Rand() & 0xffff) << 16;103Val |= uint64_t(Rand() & 0xffff) << 32;104Val |= uint64_t(Rand() & 0xffff) << 48;105return Val;106}107108/// Rand operator for STL algorithms.109ptrdiff_t operator()(ptrdiff_t y) {110return Rand64() % y;111}112113/// Make this like a C++11 random device114using result_type = uint32_t ;115116static constexpr result_type min() { return 0; }117static constexpr result_type max() { return 0x7ffff; }118119uint32_t operator()() {120uint32_t Val = Rand();121assert(Val <= max() && "Random value out of range");122return Val;123}124125private:126unsigned Seed;127};128129/// Generate an empty function with a default argument list.130Function *GenEmptyFunction(Module *M) {131// Define a few arguments132LLVMContext &Context = M->getContext();133Type* ArgsTy[] = {134PointerType::get(Context, 0),135PointerType::get(Context, 0),136PointerType::get(Context, 0),137Type::getInt32Ty(Context),138Type::getInt64Ty(Context),139Type::getInt8Ty(Context)140};141142auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false);143// Pick a unique name to describe the input parameters144Twine Name = "autogen_SD" + Twine{SeedCL};145auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M);146Func->setCallingConv(CallingConv::C);147return Func;148}149150/// A base class, implementing utilities needed for151/// modifying and adding new random instructions.152struct Modifier {153/// Used to store the randomly generated values.154using PieceTable = std::vector<Value *>;155156public:157/// C'tor158Modifier(BasicBlock *Block, PieceTable *PT, Random *R)159: BB(Block), PT(PT), Ran(R), Context(BB->getContext()) {160ScalarTypes.assign({Type::getInt1Ty(Context), Type::getInt8Ty(Context),161Type::getInt16Ty(Context), Type::getInt32Ty(Context),162Type::getInt64Ty(Context), Type::getFloatTy(Context),163Type::getDoubleTy(Context)});164165for (auto &Arg : AdditionalScalarTypes) {166Type *Ty = nullptr;167if (Arg == "half")168Ty = Type::getHalfTy(Context);169else if (Arg == "fp128")170Ty = Type::getFP128Ty(Context);171else if (Arg == "x86_fp80")172Ty = Type::getX86_FP80Ty(Context);173else if (Arg == "ppc_fp128")174Ty = Type::getPPC_FP128Ty(Context);175else if (Arg == "x86_mmx")176Ty = Type::getX86_MMXTy(Context);177else if (Arg.starts_with("i")) {178unsigned N = 0;179Arg.drop_front().getAsInteger(10, N);180if (N > 0)181Ty = Type::getIntNTy(Context, N);182}183if (!Ty) {184errs() << "Invalid IR scalar type: '" << Arg << "'!\n";185exit(1);186}187188ScalarTypes.push_back(Ty);189}190}191192/// virtual D'tor to silence warnings.193virtual ~Modifier() = default;194195/// Add a new instruction.196virtual void Act() = 0;197198/// Add N new instructions,199virtual void ActN(unsigned n) {200for (unsigned i=0; i<n; ++i)201Act();202}203204protected:205/// Return a random integer.206uint32_t getRandom() {207return Ran->Rand();208}209210/// Return a random value from the list of known values.211Value *getRandomVal() {212assert(PT->size());213return PT->at(getRandom() % PT->size());214}215216Constant *getRandomConstant(Type *Tp) {217if (Tp->isIntegerTy()) {218if (getRandom() & 1)219return ConstantInt::getAllOnesValue(Tp);220return ConstantInt::getNullValue(Tp);221} else if (Tp->isFloatingPointTy()) {222if (getRandom() & 1)223return ConstantFP::getAllOnesValue(Tp);224return ConstantFP::getZero(Tp);225}226return UndefValue::get(Tp);227}228229/// Return a random value with a known type.230Value *getRandomValue(Type *Tp) {231unsigned index = getRandom();232for (unsigned i=0; i<PT->size(); ++i) {233Value *V = PT->at((index + i) % PT->size());234if (V->getType() == Tp)235return V;236}237238// If the requested type was not found, generate a constant value.239if (Tp->isIntegerTy()) {240if (getRandom() & 1)241return ConstantInt::getAllOnesValue(Tp);242return ConstantInt::getNullValue(Tp);243} else if (Tp->isFloatingPointTy()) {244if (getRandom() & 1)245return ConstantFP::getAllOnesValue(Tp);246return ConstantFP::getZero(Tp);247} else if (auto *VTp = dyn_cast<FixedVectorType>(Tp)) {248std::vector<Constant*> TempValues;249TempValues.reserve(VTp->getNumElements());250for (unsigned i = 0; i < VTp->getNumElements(); ++i)251TempValues.push_back(getRandomConstant(VTp->getScalarType()));252253ArrayRef<Constant*> VectorValue(TempValues);254return ConstantVector::get(VectorValue);255}256257return UndefValue::get(Tp);258}259260/// Return a random value of any pointer type.261Value *getRandomPointerValue() {262unsigned index = getRandom();263for (unsigned i=0; i<PT->size(); ++i) {264Value *V = PT->at((index + i) % PT->size());265if (V->getType()->isPointerTy())266return V;267}268return UndefValue::get(pickPointerType());269}270271/// Return a random value of any vector type.272Value *getRandomVectorValue() {273unsigned index = getRandom();274for (unsigned i=0; i<PT->size(); ++i) {275Value *V = PT->at((index + i) % PT->size());276if (V->getType()->isVectorTy())277return V;278}279return UndefValue::get(pickVectorType());280}281282/// Pick a random type.283Type *pickType() {284return (getRandom() & 1) ? pickVectorType() : pickScalarType();285}286287/// Pick a random pointer type.288Type *pickPointerType() {289Type *Ty = pickType();290return PointerType::get(Ty, 0);291}292293/// Pick a random vector type.294Type *pickVectorType(VectorType *VTy = nullptr) {295296// Vectors of x86mmx are illegal; keep trying till we get something else.297Type *Ty;298do {299Ty = pickScalarType();300} while (Ty->isX86_MMXTy());301302if (VTy)303return VectorType::get(Ty, VTy->getElementCount());304305// Select either fixed length or scalable vectors with 50% probability306// (only if scalable vectors are enabled)307bool Scalable = EnableScalableVectors && getRandom() & 1;308309// Pick a random vector width in the range 2**0 to 2**4.310// by adding two randoms we are generating a normal-like distribution311// around 2**3.312unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));313return VectorType::get(Ty, width, Scalable);314}315316/// Pick a random scalar type.317Type *pickScalarType() {318return ScalarTypes[getRandom() % ScalarTypes.size()];319}320321/// Basic block to populate322BasicBlock *BB;323324/// Value table325PieceTable *PT;326327/// Random number generator328Random *Ran;329330/// Context331LLVMContext &Context;332333std::vector<Type *> ScalarTypes;334};335336struct LoadModifier: public Modifier {337LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R)338: Modifier(BB, PT, R) {}339340void Act() override {341// Try to use predefined pointers. If non-exist, use undef pointer value;342Value *Ptr = getRandomPointerValue();343Type *Ty = pickType();344Value *V = new LoadInst(Ty, Ptr, "L", BB->getTerminator());345PT->push_back(V);346}347};348349struct StoreModifier: public Modifier {350StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R)351: Modifier(BB, PT, R) {}352353void Act() override {354// Try to use predefined pointers. If non-exist, use undef pointer value;355Value *Ptr = getRandomPointerValue();356Type *ValTy = pickType();357358// Do not store vectors of i1s because they are unsupported359// by the codegen.360if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1)361return;362363Value *Val = getRandomValue(ValTy);364new StoreInst(Val, Ptr, BB->getTerminator());365}366};367368struct BinModifier: public Modifier {369BinModifier(BasicBlock *BB, PieceTable *PT, Random *R)370: Modifier(BB, PT, R) {}371372void Act() override {373Value *Val0 = getRandomVal();374Value *Val1 = getRandomValue(Val0->getType());375376// Don't handle pointer types.377if (Val0->getType()->isPointerTy() ||378Val1->getType()->isPointerTy())379return;380381// Don't handle i1 types.382if (Val0->getType()->getScalarSizeInBits() == 1)383return;384385bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy();386Instruction* Term = BB->getTerminator();387unsigned R = getRandom() % (isFloat ? 7 : 13);388Instruction::BinaryOps Op;389390switch (R) {391default: llvm_unreachable("Invalid BinOp");392case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; }393case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; }394case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; }395case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; }396case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; }397case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; }398case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; }399case 7: {Op = Instruction::Shl; break; }400case 8: {Op = Instruction::LShr; break; }401case 9: {Op = Instruction::AShr; break; }402case 10:{Op = Instruction::And; break; }403case 11:{Op = Instruction::Or; break; }404case 12:{Op = Instruction::Xor; break; }405}406407PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term));408}409};410411/// Generate constant values.412struct ConstModifier: public Modifier {413ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R)414: Modifier(BB, PT, R) {}415416void Act() override {417Type *Ty = pickType();418419if (Ty->isVectorTy()) {420switch (getRandom() % 2) {421case 0: if (Ty->isIntOrIntVectorTy())422return PT->push_back(ConstantVector::getAllOnesValue(Ty));423break;424case 1: if (Ty->isIntOrIntVectorTy())425return PT->push_back(ConstantVector::getNullValue(Ty));426}427}428429if (Ty->isFloatingPointTy()) {430// Generate 128 random bits, the size of the (currently)431// largest floating-point types.432uint64_t RandomBits[2];433for (unsigned i = 0; i < 2; ++i)434RandomBits[i] = Ran->Rand64();435436APInt RandomInt(Ty->getPrimitiveSizeInBits(), ArrayRef(RandomBits));437APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);438439if (getRandom() & 1)440return PT->push_back(ConstantFP::getZero(Ty));441return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat));442}443444if (Ty->isIntegerTy()) {445switch (getRandom() % 7) {446case 0:447return PT->push_back(ConstantInt::get(448Ty, APInt::getAllOnes(Ty->getPrimitiveSizeInBits())));449case 1:450return PT->push_back(451ConstantInt::get(Ty, APInt::getZero(Ty->getPrimitiveSizeInBits())));452case 2:453case 3:454case 4:455case 5:456case 6:457PT->push_back(ConstantInt::get(Ty, getRandom()));458}459}460}461};462463struct AllocaModifier: public Modifier {464AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R)465: Modifier(BB, PT, R) {}466467void Act() override {468Type *Tp = pickType();469const DataLayout &DL = BB->getDataLayout();470PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(),471"A", BB->getFirstNonPHI()));472}473};474475struct ExtractElementModifier: public Modifier {476ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)477: Modifier(BB, PT, R) {}478479void Act() override {480Value *Val0 = getRandomVectorValue();481Value *V = ExtractElementInst::Create(482Val0,483getRandomValue(Type::getInt32Ty(BB->getContext())),484"E", BB->getTerminator());485return PT->push_back(V);486}487};488489struct ShuffModifier: public Modifier {490ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R)491: Modifier(BB, PT, R) {}492493void Act() override {494Value *Val0 = getRandomVectorValue();495Value *Val1 = getRandomValue(Val0->getType());496497// Can't express arbitrary shufflevectors for scalable vectors498if (isa<ScalableVectorType>(Val0->getType()))499return;500501unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements();502std::vector<Constant*> Idxs;503504Type *I32 = Type::getInt32Ty(BB->getContext());505for (unsigned i=0; i<Width; ++i) {506Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2));507// Pick some undef values.508if (!(getRandom() % 5))509CI = UndefValue::get(I32);510Idxs.push_back(CI);511}512513Constant *Mask = ConstantVector::get(Idxs);514515Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff",516BB->getTerminator());517PT->push_back(V);518}519};520521struct InsertElementModifier: public Modifier {522InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)523: Modifier(BB, PT, R) {}524525void Act() override {526Value *Val0 = getRandomVectorValue();527Value *Val1 = getRandomValue(Val0->getType()->getScalarType());528529Value *V = InsertElementInst::Create(530Val0, Val1,531getRandomValue(Type::getInt32Ty(BB->getContext())),532"I", BB->getTerminator());533return PT->push_back(V);534}535};536537struct CastModifier: public Modifier {538CastModifier(BasicBlock *BB, PieceTable *PT, Random *R)539: Modifier(BB, PT, R) {}540541void Act() override {542Value *V = getRandomVal();543Type *VTy = V->getType();544Type *DestTy = pickScalarType();545546// Handle vector casts vectors.547if (VTy->isVectorTy())548DestTy = pickVectorType(cast<VectorType>(VTy));549550// no need to cast.551if (VTy == DestTy) return;552553// Pointers:554if (VTy->isPointerTy()) {555if (!DestTy->isPointerTy())556DestTy = PointerType::get(DestTy, 0);557return PT->push_back(558new BitCastInst(V, DestTy, "PC", BB->getTerminator()));559}560561unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits();562unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits();563564// Generate lots of bitcasts.565if ((getRandom() & 1) && VSize == DestSize) {566return PT->push_back(567new BitCastInst(V, DestTy, "BC", BB->getTerminator()));568}569570// Both types are integers:571if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) {572if (VSize > DestSize) {573return PT->push_back(574new TruncInst(V, DestTy, "Tr", BB->getTerminator()));575} else {576assert(VSize < DestSize && "Different int types with the same size?");577if (getRandom() & 1)578return PT->push_back(579new ZExtInst(V, DestTy, "ZE", BB->getTerminator()));580return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator()));581}582}583584// Fp to int.585if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) {586if (getRandom() & 1)587return PT->push_back(588new FPToSIInst(V, DestTy, "FC", BB->getTerminator()));589return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator()));590}591592// Int to fp.593if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) {594if (getRandom() & 1)595return PT->push_back(596new SIToFPInst(V, DestTy, "FC", BB->getTerminator()));597return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator()));598}599600// Both floats.601if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) {602if (VSize > DestSize) {603return PT->push_back(604new FPTruncInst(V, DestTy, "Tr", BB->getTerminator()));605} else if (VSize < DestSize) {606return PT->push_back(607new FPExtInst(V, DestTy, "ZE", BB->getTerminator()));608}609// If VSize == DestSize, then the two types must be fp128 and ppc_fp128,610// for which there is no defined conversion. So do nothing.611}612}613};614615struct SelectModifier: public Modifier {616SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R)617: Modifier(BB, PT, R) {}618619void Act() override {620// Try a bunch of different select configuration until a valid one is found.621Value *Val0 = getRandomVal();622Value *Val1 = getRandomValue(Val0->getType());623624Type *CondTy = Type::getInt1Ty(Context);625626// If the value type is a vector, and we allow vector select, then in 50%627// of the cases generate a vector select.628if (auto *VTy = dyn_cast<VectorType>(Val0->getType()))629if (getRandom() & 1)630CondTy = VectorType::get(CondTy, VTy->getElementCount());631632Value *Cond = getRandomValue(CondTy);633Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator());634return PT->push_back(V);635}636};637638struct CmpModifier: public Modifier {639CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R)640: Modifier(BB, PT, R) {}641642void Act() override {643Value *Val0 = getRandomVal();644Value *Val1 = getRandomValue(Val0->getType());645646if (Val0->getType()->isPointerTy()) return;647bool fp = Val0->getType()->getScalarType()->isFloatingPointTy();648649int op;650if (fp) {651op = getRandom() %652(CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) +653CmpInst::FIRST_FCMP_PREDICATE;654} else {655op = getRandom() %656(CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) +657CmpInst::FIRST_ICMP_PREDICATE;658}659660Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp,661(CmpInst::Predicate)op, Val0, Val1, "Cmp",662BB->getTerminator());663return PT->push_back(V);664}665};666667} // end anonymous namespace668669static void FillFunction(Function *F, Random &R) {670// Create a legal entry block.671BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F);672ReturnInst::Create(F->getContext(), BB);673674// Create the value table.675Modifier::PieceTable PT;676677// Consider arguments as legal values.678for (auto &arg : F->args())679PT.push_back(&arg);680681// List of modifiers which add new random instructions.682std::vector<std::unique_ptr<Modifier>> Modifiers;683Modifiers.emplace_back(new LoadModifier(BB, &PT, &R));684Modifiers.emplace_back(new StoreModifier(BB, &PT, &R));685auto SM = Modifiers.back().get();686Modifiers.emplace_back(new ExtractElementModifier(BB, &PT, &R));687Modifiers.emplace_back(new ShuffModifier(BB, &PT, &R));688Modifiers.emplace_back(new InsertElementModifier(BB, &PT, &R));689Modifiers.emplace_back(new BinModifier(BB, &PT, &R));690Modifiers.emplace_back(new CastModifier(BB, &PT, &R));691Modifiers.emplace_back(new SelectModifier(BB, &PT, &R));692Modifiers.emplace_back(new CmpModifier(BB, &PT, &R));693694// Generate the random instructions695AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas696ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants697698for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i)699for (auto &Mod : Modifiers)700Mod->Act();701702SM->ActN(5); // Throw in a few stores.703}704705static void IntroduceControlFlow(Function *F, Random &R) {706std::vector<Instruction*> BoolInst;707for (auto &Instr : F->front()) {708if (Instr.getType() == IntegerType::getInt1Ty(F->getContext()))709BoolInst.push_back(&Instr);710}711712llvm::shuffle(BoolInst.begin(), BoolInst.end(), R);713714for (auto *Instr : BoolInst) {715BasicBlock *Curr = Instr->getParent();716BasicBlock::iterator Loc = Instr->getIterator();717BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF");718Instr->moveBefore(Curr->getTerminator());719if (Curr != &F->getEntryBlock()) {720BranchInst::Create(Curr, Next, Instr, Curr->getTerminator());721Curr->getTerminator()->eraseFromParent();722}723}724}725726} // end namespace llvm727728int main(int argc, char **argv) {729using namespace llvm;730731InitLLVM X(argc, argv);732cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()});733cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");734735LLVMContext Context;736auto M = std::make_unique<Module>("/tmp/autogen.bc", Context);737Function *F = GenEmptyFunction(M.get());738739// Pick an initial seed value740Random R(SeedCL);741// Generate lots of random instructions inside a single basic block.742FillFunction(F, R);743// Break the basic block into many loops.744IntroduceControlFlow(F, R);745746// Figure out what stream we are supposed to write to...747std::unique_ptr<ToolOutputFile> Out;748// Default to standard output.749if (OutputFilename.empty())750OutputFilename = "-";751752std::error_code EC;753Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));754if (EC) {755errs() << EC.message() << '\n';756return 1;757}758759// Check that the generated module is accepted by the verifier.760if (verifyModule(*M.get(), &Out->os()))761report_fatal_error("Broken module found, compilation aborted!");762763// Output textual IR.764M->print(Out->os(), nullptr);765766Out->keep();767768return 0;769}770771772