void Codegen::createPasses() { llvm::TargetMachine *tm = targetMachine(); // llvm::DataLayout *dl = new llvm::DataLayout(&llvmModule()); modulePasses = new llvm::PassManager(); // modulePasses->add(dl); functionPasses = new llvm::FunctionPassManager(&llvmModule()); // functionPasses->add(dl); tm->addAnalysisPasses(*modulePasses); tm->addAnalysisPasses(*functionPasses); llvm::PassManagerBuilder pmBuilder; pmBuilder.OptLevel = options.optLevel; llvm::Triple targetTriple(llvmModule().getTargetTriple()); pmBuilder.LibraryInfo = new llvm::TargetLibraryInfo(targetTriple); if (nativeEnabled()) { codegenPasses = new llvm::PassManager(); // codegenPasses->add(dl); //codegenPasses->add(pmBuilder.LibraryInfo); tm->addAnalysisPasses(*codegenPasses); } unsigned inlineThreshold = 225; if (options.optLevel > 2) { inlineThreshold = 275; modulePasses->add(llvm::createStripSymbolsPass(true)); } pmBuilder.Inliner = llvm::createFunctionInliningPass(inlineThreshold); pmBuilder.populateFunctionPassManager(*functionPasses); pmBuilder.populateModulePassManager(*modulePasses); }
std::string generatePtx(llvm::Module *module, int devMajor, int devMinor) { std::string mcpu; if ((devMajor == 3 && devMinor >= 5) || devMajor > 3) { mcpu = "sm_35"; } else if (devMajor >= 3 && devMinor >= 0) { mcpu = "sm_30"; } else { mcpu = "sm_20"; } // Select target given the module's triple llvm::Triple triple(module->getTargetTriple()); std::string errStr; const llvm::Target* target = nullptr; target = llvm::TargetRegistry::lookupTarget(triple.str(), errStr); iassert(target) << errStr; llvm::TargetOptions targetOptions; std::string features = "+ptx40"; std::unique_ptr<llvm::TargetMachine> targetMachine( target->createTargetMachine(triple.str(), mcpu, features, targetOptions, // llvm::Reloc::PIC_, llvm::Reloc::Default, llvm::CodeModel::Default, llvm::CodeGenOpt::Default)); // Make a passmanager and add emission to string llvm::legacy::PassManager pm; pm.add(new llvm::TargetLibraryInfoWrapperPass(triple)); // Set up constant NVVM reflect mapping llvm::StringMap<int> reflectMapping; reflectMapping["__CUDA_FTZ"] = 1; // Flush denormals to zero pm.add(llvm::createNVVMReflectPass(reflectMapping)); pm.add(llvm::createAlwaysInlinerPass()); targetMachine->Options.MCOptions.AsmVerbose = true; llvm::SmallString<8> ptxStr; llvm::raw_svector_ostream outStream(ptxStr); outStream.SetUnbuffered(); bool failed = targetMachine->addPassesToEmitFile( pm, outStream, targetMachine->CGFT_AssemblyFile, false); iassert(!failed); pm.run(*module); outStream.flush(); return ptxStr.str(); }
void Codegen::emitCode(llvm::raw_ostream *os) { llvm::formatted_raw_ostream formattedOS; createPasses(); llvm::TargetMachine::CodeGenFileType cgft = llvm::TargetMachine::CGFT_AssemblyFile; switch (options.type) { case codegen::LLVM: formattedOS.setStream(*os, llvm::formatted_raw_ostream::PRESERVE_STREAM); modulePasses->add(llvm::createPrintModulePass(*os)); break; case codegen::BC: modulePasses->add(llvm::createBitcodeWriterPass(*os)); break; case codegen::ASM: break; case codegen::OBJ: cgft = llvm::TargetMachine::CGFT_ObjectFile; break; default: // screem break; } functionPasses->doInitialization(); for (llvm::Module::iterator I = llvmModule().begin(), E = llvmModule().end(); I != E; ++I) if (!I->isDeclaration()) functionPasses->run(*I); functionPasses->doFinalization(); modulePasses->run(llvmModule()); if (codegenPasses) { formattedOS.setStream(*os, llvm::formatted_raw_ostream::PRESERVE_STREAM); if (targetMachine()->addPassesToEmitFile(*codegenPasses, formattedOS, cgft)) { std::cout << "pass fail"; } codegenPasses->run(llvmModule()); } }
// GenerateMachineCode may modify the Module object passed in. Should we clone it first? void GenerateMachineCode(llvm::raw_ostream& os, IRModuleEmitter& moduleEmitter, OutputFileType fileType, const MachineCodeOutputOptions& ellOptions) { llvm::Module& module = *(moduleEmitter.GetLLVMModule()); llvm::LLVMContext context; context.setDiscardValueNames(false); // Don't throw away names of non-global values // Verify module if requested if (ellOptions.verifyModule && llvm::verifyModule(module)) { throw EmitterException(EmitterError::unexpected, "Module verification failed"); } // Set the triple for the module, and retrieve it as a Triple object auto targetTripleStr = ellOptions.targetDevice.triple.empty() ? llvm::sys::getDefaultTargetTriple() : ellOptions.targetDevice.triple; module.setTargetTriple(llvm::Triple::normalize(targetTripleStr)); llvm::Triple targetTriple{ module.getTargetTriple() }; // Get the target-specific parser. Note that targetTriple can be modified by lookupTarget. std::string error; const llvm::Target* target = llvm::TargetRegistry::lookupTarget(ellOptions.targetDevice.architecture, targetTriple, error); if (!target) { throw EmitterException(EmitterError::unexpected, std::string("Couldn't create target ") + error); } llvm::TargetOptions targetOptions = MakeTargetOptions(); targetOptions.MCOptions.AsmVerbose = ellOptions.verboseOutput; targetOptions.FloatABIType = ellOptions.floatABI; llvm::Reloc::Model relocModel = llvm::Reloc::Static; llvm::CodeModel::Model codeModel = llvm::CodeModel::Default; std::unique_ptr<llvm::TargetMachine> targetMachine(target->createTargetMachine(targetTriple.getTriple(), ellOptions.targetDevice.cpu, ellOptions.targetDevice.features, targetOptions, relocModel, codeModel, ellOptions.optimizationLevel)); if (!targetMachine) { throw EmitterException(EmitterError::unexpected, "Unable to allocate target machine"); } // Build up all of the passes that we want to apply to the module llvm::legacy::PassManager passManager; // Get a targetLibraryInfo describing the library functions available for this triple, // and any special processing we might want to do. For instance, if we want to // disable all builtin library functions, do this: `targetLibraryInfo.disableAllFunctions();` llvm::TargetLibraryInfoImpl targetLibraryInfo(llvm::Triple(module.getTargetTriple())); // ...and add it to the pass manager, so various optimizations can be done passManager.add(new llvm::TargetLibraryInfoWrapperPass(targetLibraryInfo)); // Set the data layout of the module to match the target machine module.setDataLayout(targetMachine->createDataLayout()); // Override function attributes based on cpu and features if (ellOptions.targetDevice.cpu != "") { SetFunctionAttributes(ellOptions.targetDevice.cpu, ellOptions.targetDevice.features, module); } // Set up passes to emit code to a memory stream llvm::SmallVector<char, 0> buffer; llvm::raw_svector_ostream bufferedStream(buffer); if (targetMachine->addPassesToEmitFile(passManager, bufferedStream, fileType, ellOptions.verifyModule, nullptr, nullptr, nullptr, nullptr)) { throw EmitterException(EmitterError::unexpected, "target does not support generation of this file type!"); } // Finally, run the passes to emit code to the straem passManager.run(module); // run() returns a bool indicating if the module was modified (true if it was) if (moduleEmitter.GetDiagnosticHandler().HadError()) { throw EmitterException(EmitterError::unexpected, "Error compiling module"); } // Write memory buffer to our output stream os << buffer; }
VirtualMachine::VirtualMachine(llvm::LLVMContext &context, const VirtualMachineOptions &opts) : context(context), options(opts) { #ifdef USE_ALL_TARGETS // Initialize all targets first llvm::InitializeAllTargets(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); #else // Initialize the native target first llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); #endif // Use the default target when no specified. if(options.Triple.empty()) options.Triple = llvm::sys::getDefaultTargetTriple(); triple.setTriple(options.Triple); // Lookup the the requested target. std::string error; target = llvm::TargetRegistry::lookupTarget(options.Triple, error); if(!target) throw VirtualMachineException("Failed to get target for " + options.Triple); // Create the target machine to get data about the target. std::auto_ptr<llvm::TargetMachine> targetMachine(target->createTargetMachine(options.Triple, options.Cpu, options.FeatureString, options.TargetOptions)); if(!targetMachine.get()) throw VirtualMachineException("Failed to create a target machine for " + options.Triple); // Copy the target data of the machine. targetData = new llvm::TargetData(*targetMachine->getTargetData()); // Create the type data. dataImpl = new _VirtualMachineDataImpl(this, context, targetData); // Initialize to null some variables. executionEngine = NULL; runtimeModule = NULL; // Base classes. objectClass = NULL; typeClass = NULL; stringClass = NULL; closureClass = NULL; arrayClass = NULL; valueTypeClass = NULL; enumClass = NULL; delegateClass = NULL; // Special attributes. threadStaticAttribute = NULL; chelaIntrinsicAttribute = NULL; // Kernel data holders streamHolderClass = NULL; streamHolder1DClass = NULL; streamHolder2DClass = NULL; streamHolder3DClass = NULL; uniformHolderClass = NULL; // Reflection info. assemblyClass = NULL; constructorInfoClass = NULL; eventInfoClass = NULL; fieldInfoClass = NULL; memberInfoClass = NULL; methodInfoClass = NULL; parameterInfoClass = NULL; propertyInfoClass = NULL; // Memory management. unmanagedAlloc = NULL; unmanagedAllocArray = NULL; unmanagedFree = NULL; unmanagedFreeArray = NULL; managedAlloc = NULL; addReference = NULL; releaseReference = NULL; // Casting. objectDownCast = NULL; ifaceDownCast = NULL; ifaceCrossCast = NULL; checkCast = NULL; // Type checking. isRefType = NULL; // Exception handling. ehPersonality = NULL; ehThrow = NULL; ehRead = NULL; // Implicit checks. throwNull = NULL; throwBound = NULL; // Kernel binder helpers. computeIsCpu = NULL; computeCpuBind = NULL; computeBind = NULL; // Initialize the sys layer. InitSysLayer(); }
llvm::DataLayout InternalContext::dataLayout() const { return targetMachine().createDataLayout(); }
int main(int argc, const char * argv[]) { // Usage Message (TODO: Improve) if (argc < 3) { std::cerr << "Usage: " << argv[0] << " <FileName>\n" << "Compiles the file given by <FileName>\n"; return 1; } // Read in the file passed as the first argument std::ifstream fileStream; fileStream.open(argv[1]); // We'll output to the file passed in as the second argument std::error_code ec; auto openflags = llvm::sys::fs::F_None; auto out = std::make_unique<llvm::tool_output_file>(argv[2], ec, openflags); if (ec) { std::cerr << argv[0] << ": " << ec.message() << "\n"; return 1; } // Parse it! auto lex = Lexer(&fileStream); auto stmts = parse(&lex); // std::cout << "Result of parsing: \n"; // for (auto &stmt : stmts) { // std::cout << *stmt << ";\n"; // } auto prgm = Program(); prgm.addItems(stmts); prgm.finalize(); auto mod = prgm.module; /* DEBUG */ // mod->dump(); llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); llvm::InitializeNativeTargetAsmParser(); llvm::PassRegistry *registry = llvm::PassRegistry::getPassRegistry(); llvm::initializeCore(*registry); llvm::initializeCodeGen(*registry); llvm::initializeLoopStrengthReducePass(*registry); llvm::initializeLowerIntrinsicsPass(*registry); llvm::initializeUnreachableBlockElimPass(*registry); llvm::Triple targetTriple(mod->getTargetTriple()); if (targetTriple.getTriple().empty()) { targetTriple.setTriple(llvm::sys::getDefaultTargetTriple()); } std::cout << "Target Triple: " << targetTriple.getTriple() << "\n"; std::string error; const llvm::Target *target = llvm::TargetRegistry::lookupTarget("", targetTriple, error); if (! target) { std::cerr << argv[0] << ": " << error; return 1; } auto optLvl = llvm::CodeGenOpt::Default; switch ('0') { // TEmporary default: std::cerr << argv[0] << ": invalid optimization level.\n"; return 1; case ' ': break; case '0': optLvl = llvm::CodeGenOpt::None; break; case '1': optLvl = llvm::CodeGenOpt::Less; break; case '2': optLvl = llvm::CodeGenOpt::Default; break; case '3': optLvl = llvm::CodeGenOpt::Aggressive; break; } // llvm::TargetOptions options; // TODO: llc line 268 std::unique_ptr<llvm::TargetMachine> targetMachine(target->createTargetMachine(targetTriple.getTriple(), llvm::sys::getHostCPUName(), "", llvm::TargetOptions(), llvm::Reloc::Default, llvm::CodeModel::Default, optLvl)); assert(targetMachine && "Could not allocate target machine!"); llvm::PassManager passmanager; llvm::TargetLibraryInfo *TLI = new llvm::TargetLibraryInfo(targetTriple); passmanager.add(TLI); if (const llvm::DataLayout *datalayout = targetMachine->getSubtargetImpl()->getDataLayout()) mod->setDataLayout(datalayout); llvm::formatted_raw_ostream ostream(out->os()); // Ask the target to add backend passes as necessary. if (targetMachine->addPassesToEmitFile(passmanager, ostream, llvm::TargetMachine::CGFT_ObjectFile)) { std::cerr << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; } passmanager.run(*mod); out->keep(); return 0; }