bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile, std::string &Sysroot, std::string &OutputFile, raw_ostream *&OS) { // If no output file was provided, figure out where this module would go // in the module cache. if (CI.getFrontendOpts().OutputFile.empty()) { HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); CI.getFrontendOpts().OutputFile = HS.getModuleFileName(CI.getLangOpts().CurrentModule, ModuleMapForUniquing->getName()); } // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true, /*CreateMissingDirectories=*/true); if (!OS) return true; OutputFile = CI.getFrontendOpts().OutputFile; return false; }
void CreateOutput(CompilerInstance& CI) { //llvm::errs() << __FUNCTION__ << ":" << CI.getFrontendOpts().OutputFile << "\n"; if (output_) return; std::string errMsg; output_ = CI.createOutputFile("", errMsg, true, true, CI.getFrontendOpts().OutputFile, "fanout"); if (!output_) llvm::errs() << "Failed to create output file:" << errMsg << "\n"; }
std::unique_ptr<llvm::raw_pwrite_stream> GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile, std::string &OutputFile) { // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. std::unique_ptr<raw_pwrite_stream> OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true); if (!OS) return nullptr; OutputFile = CI.getFrontendOpts().OutputFile; return OS; }
std::unique_ptr<raw_pwrite_stream> GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { // If no output file was provided, figure out where this module would go // in the module cache. if (CI.getFrontendOpts().OutputFile.empty()) { HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); CI.getFrontendOpts().OutputFile = HS.getModuleFileName(CI.getLangOpts().CurrentModule, ModuleMapForUniquing->getName(), /*UsePrebuiltPath=*/false); } // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true, /*CreateMissingDirectories=*/true); }
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, llvm::StringRef InFile, std::string &Sysroot, llvm::raw_ostream *&OS, bool &Chaining) { Sysroot = CI.getHeaderSearchOpts().Sysroot; if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); return true; } // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile); if (!OS) return true; Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH && !CI.getPreprocessorOpts().ImplicitPCHInclude.empty(); return false; }
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile, std::string &Sysroot, std::string &OutputFile, raw_ostream *&OS) { Sysroot = CI.getHeaderSearchOpts().Sysroot; if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); return true; } // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true); if (!OS) return true; OutputFile = CI.getFrontendOpts().OutputFile; return false; }
static int CompileSubprocess(const char **argv, int argc, sys::Path &ResourceDir, bool bugreport, bool versionOnly, sys::Path &apiMapPath) { std::vector<char*> llvmArgs; char apim[] = "-clam-apimap"; llvmArgs.push_back((char*)argv[0]); llvmArgs.push_back(apim); llvmArgs.push_back((char*)apiMapPath.c_str()); // Split args into cc1 and LLVM args, separator is -- int cc1_argc; for (cc1_argc=1;cc1_argc<argc;cc1_argc++) { if (StringRef(argv[cc1_argc]) == "--") { for (int i=cc1_argc+1;i<argc;i++) { llvmArgs.push_back((char*)argv[i]); } break; } } // Initialize CompilerInstance from commandline args CompilerInstance Clang; Clang.setLLVMContext(new llvm::LLVMContext); LLVMInitializeClamBCTargetInfo(); LLVMInitializeClamBCTarget(); TextDiagnosticBuffer DiagsBuffer; Diagnostic Diags(&DiagsBuffer); CompilerInvocation::CreateFromArgs(Clang.getInvocation(), argv+1, argv+cc1_argc, Diags); FrontendOptions &FrontendOpts = Clang.getInvocation().getFrontendOpts(); // Handle --version if (FrontendOpts.ShowVersion || versionOnly) { printVersion(outs(), true); exit(0); } DiagnosticOptions &DiagOpts = Clang.getInvocation().getDiagnosticOpts(); DiagOpts.ShowOptionNames = DiagOpts.ShowColors = 1; DiagOpts.MessageLength = 80;// we are writing to a file DiagOpts.Warnings.push_back("all"); DiagOpts.Warnings.push_back("no-pointer-sign"); Clang.createDiagnostics(argc-1, const_cast<char**>(argv+1)); if (!Clang.hasDiagnostics()) return 2; Clang.getInvocation().getHeaderSearchOpts().ResourceDir = ResourceDir.str(); // Set default options LangOptions &LangOpts = Clang.getInvocation().getLangOpts(); // This is a freestanding environment, without libc, etc. LangOpts.Freestanding = 1; HeaderSearchOptions &HeaderSearchOpts = Clang.getInvocation().getHeaderSearchOpts(); HeaderSearchOpts.UseStandardIncludes = 0; if (bugreport) HeaderSearchOpts.Verbose = 1; if (FrontendOpts.ProgramAction != frontend::PrintPreprocessedInput) FrontendOpts.ProgramAction = frontend::EmitBC; if (bugreport) FrontendOpts.ProgramAction = frontend::PrintPreprocessedInput; // Don't bother freeing of memory on exit FrontendOpts.DisableFree = 1; CodeGenOptions &Opts = Clang.getInvocation().getCodeGenOpts(); Opts.Inlining = CodeGenOptions::OnlyAlwaysInlining; // always generate debug info, so that ClamBC backend can output sourcelevel // diagnostics. Opts.DebugInfo = true; // FIXME: once the verifier can work w/o targetdata, and targetdate opts set // DisableLLVMOpts to true! // This is needed to avoid target-specific optimizations Opts.DisableLLVMOpts = false; AnalyzerOptions &AOpts = Clang.getInvocation().getAnalyzerOpts(); AOpts.AnalysisList.push_back(WarnDeadStores); AOpts.AnalysisList.push_back(WarnUninitVals); AOpts.AnalysisList.push_back(SecuritySyntacticChecks); AOpts.AnalysisList.push_back(WarnSizeofPointer); // Set triple Clang.getInvocation().getTargetOpts().Triple = "clambc-generic-generic"; // Set default include Clang.getInvocation().getPreprocessorOpts().Includes.push_back("bytecode.h"); // Set an LLVM error handler. llvm::llvm_install_error_handler(LLVMErrorHandler, static_cast<void*>(&Clang.getDiagnostics())); DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics()); // If there were any errors in processing arguments, exit now. if (Clang.getDiagnostics().getNumErrors()) return 1; // Create the target instance. //TODO: directly create a clambc target Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), Clang.getTargetOpts())); if (!Clang.hasTarget()) return 1; // Inform the target of the language options Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); if (Clang.getHeaderSearchOpts().Verbose) { llvm::errs() << "clang -cc1 version " CLANG_VERSION_STRING << " based upon " << PACKAGE_STRING << " hosted on " << llvm::sys::getHostTriple() << "\n"; // Convert the invocation back to argument strings. std::vector<std::string> InvocationArgs; Clang.getInvocation().toArgs(InvocationArgs); // Dump the converted arguments. llvm::SmallVector<const char*, 32> Invocation2Args; llvm::errs() << "invocation argv :"; for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) { Invocation2Args.push_back(InvocationArgs[i].c_str()); llvm::errs() << " \"" << InvocationArgs[i] << '"'; } llvm::errs() << "\n"; } std::string Input = FrontendOpts.Inputs[0].second; if (Input == "-" && bugreport) return 2; raw_fd_ostream *fd = 0; if (FrontendOpts.ProgramAction == frontend::EmitBC) { // replace output file of compiler with a tempfile, // and save the final output filename. std::string FinalOutput = FrontendOpts.OutputFile; if (FinalOutput.empty()) { if (Input == "-") FinalOutput = "-"; else { sys::Path P(sys::Path(Input).getBasename()); P.appendSuffix("cbc"); FinalOutput = P.str(); } } llvm::raw_fd_ostream *tmpfd; std::string Err2; fd = Clang.createOutputFile(FinalOutput, Err2, false); if (!fd) { Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << Err2; return 1; } sys::Path P = sys::Path(FinalOutput); P.eraseSuffix(); P.appendSuffix("tmp.bc"); FrontendOpts.OutputFile = P.str(); tmpfd = Clang.createOutputFile(P.str(), Err2, true); if (!tmpfd) { Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << Err2; return 1; } delete tmpfd; sys::RemoveFileOnSignal(sys::Path(FrontendOpts.OutputFile)); } if (!FrontendOpts.Inputs.empty()) { char srcp[] = "-clambc-src"; llvmArgs.push_back(srcp); llvmArgs.push_back(strdup(Input.c_str())); } // Parse LLVM commandline args cl::ParseCommandLineOptions(llvmArgs.size(), &llvmArgs[0]); std::string re2cpath = getTmpDir(); if (re2cpath.empty()) { llvm::errs()<< "Failed to create temporary file for re2c-out!\n"; return 2; } re2cpath += "/clambc-compiler-re2c-out"; sys::Path TmpRe2C(re2cpath); if (!FrontendOpts.Inputs.empty()) { char re2c_args[] = "--no-generation-date"; char re2c_o[] = "-o"; char name[] = ""; char *args[6] = { name, re2c_args, re2c_o, NULL, NULL, NULL }; args[4] = strdup(Input.c_str()); std::string ErrMsg(""); if (TmpRe2C.createTemporaryFileOnDisk(true, &ErrMsg)) { Clang.getDiagnostics().Report(clang::diag::err_drv_unable_to_make_temp) << ErrMsg; return 1; } sys::RemoveFileOnSignal(TmpRe2C); args[3] = strdup(TmpRe2C.str().c_str()); int ret = re2c_main(5, args); if (ret) { Clang.getDiagnostics().Report(clang::diag::err_drv_command_failed) << "re2c" << ret; return 1; } Input = TmpRe2C.str(); } // Create a file manager object to provide access to and cache the // filesystem. Clang.createFileManager(); // Create the source manager. Clang.createSourceManager(); // Create the preprocessor. Clang.createPreprocessor(); llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang)); if (Act && Act->BeginSourceFile(Clang, Input, false)) { Act->Execute(); Act->EndSourceFile(); } TmpRe2C.eraseFromDisk();// erase tempfile int ret = Clang.getDiagnostics().getNumErrors() != 0; if (ret) return ret; if (FrontendOpts.ProgramAction != frontend::EmitBC) { // stop processing if not compiling a final .cbc file return 0; } ret = compileInternal(FrontendOpts.OutputFile.c_str(), Opts.OptimizationLevel, Opts.OptimizeSize, argv[0], fd, Clang); // Erase temp file, we need to do this here since OutputFile is a tempfile // only if action was EmitBC sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); return ret; }