int main(int argc, char **argv) { INITIALIZE_LLVM(argc, argv); llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL optimizer\n"); if (PrintStats) llvm::EnableStatistics(); CompilerInvocation Invocation; Invocation.setMainExecutablePath( llvm::sys::fs::getMainExecutable(argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable))); // Give the context the list of search paths to use for modules. Invocation.setImportSearchPaths(ImportPaths); std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths; for (const auto &path : FrameworkPaths) { FramePaths.push_back({path, /*isSystem=*/false}); } Invocation.setFrameworkSearchPaths(FramePaths); // Set the SDK path and target if given. if (SDKPath.getNumOccurrences() == 0) { const char *SDKROOT = getenv("SDKROOT"); if (SDKROOT) SDKPath = SDKROOT; } if (!SDKPath.empty()) Invocation.setSDKPath(SDKPath); if (!Target.empty()) Invocation.setTargetTriple(Target); if (!ResourceDir.empty()) Invocation.setRuntimeResourcePath(ResourceDir); Invocation.getFrontendOptions().EnableResilience = EnableResilience; // Set the module cache path. If not passed in we use the default swift module // cache. Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath; Invocation.setParseStdlib(); Invocation.getLangOptions().DisableAvailabilityChecking = true; Invocation.getLangOptions().EnableAccessControl = false; Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false; Invocation.getLangOptions().EnableObjCInterop = llvm::Triple(Target).isOSDarwin(); Invocation.getLangOptions().ASTVerifierProcessCount = ASTVerifierProcessCount; Invocation.getLangOptions().ASTVerifierProcessId = ASTVerifierProcessId; Invocation.getLangOptions().EnableSILOpaqueValues = EnableSILOpaqueValues; // Setup the SIL Options. SILOptions &SILOpts = Invocation.getSILOptions(); SILOpts.InlineThreshold = SILInlineThreshold; SILOpts.VerifyAll = EnableSILVerifyAll; SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts; SILOpts.AssertConfig = AssertConfId; if (OptimizationGroup != OptGroup::Diagnostics) SILOpts.Optimization = SILOptions::SILOptMode::Optimize; SILOpts.EnableSILOwnership = EnableSILOwnershipOpt; SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; switch (EnforceExclusivity) { case EnforceExclusivityMode::Unchecked: // This option is analogous to the -Ounchecked optimization setting. // It will disable dynamic checking but still diagnose statically. SILOpts.EnforceExclusivityStatic = true; SILOpts.EnforceExclusivityDynamic = false; break; case EnforceExclusivityMode::Checked: SILOpts.EnforceExclusivityStatic = true; SILOpts.EnforceExclusivityDynamic = true; break; case EnforceExclusivityMode::DynamicOnly: // This option is intended for staging purposes. The intent is that // it will eventually be removed. SILOpts.EnforceExclusivityStatic = false; SILOpts.EnforceExclusivityDynamic = true; break; case EnforceExclusivityMode::None: // This option is for staging purposes. SILOpts.EnforceExclusivityStatic = false; SILOpts.EnforceExclusivityDynamic = false; break; } // Load the input file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(InputFilename); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } // If it looks like we have an AST, set the source file kind to SIL and the // name of the module to the file's name. Invocation.addInputBuffer(FileBufOrErr.get().get()); serialization::ExtendedValidationInfo extendedInfo; auto result = serialization::validateSerializedAST( FileBufOrErr.get()->getBuffer(), &extendedInfo); bool HasSerializedAST = result.status == serialization::Status::Valid; if (HasSerializedAST) { const StringRef Stem = ModuleName.size() ? StringRef(ModuleName) : llvm::sys::path::stem(InputFilename); Invocation.setModuleName(Stem); Invocation.setInputKind(InputFileKind::IFK_Swift_Library); } else { const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main"; Invocation.setModuleName(Name); Invocation.setInputKind(InputFileKind::IFK_SIL); } CompilerInstance CI; PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); if (!PerformWMO) { auto &FrontendOpts = Invocation.getFrontendOptions(); if (!InputFilename.empty() && InputFilename != "-") { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputFilenames.size()); } else { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer); } } if (CI.setup(Invocation)) return 1; CI.performSema(); // If parsing produced an error, don't run any passes. if (CI.getASTContext().hadError()) return 1; // Load the SIL if we have a module. We have to do this after SILParse // creating the unfortunate double if statement. if (HasSerializedAST) { assert(!CI.hasSILModule() && "performSema() should not create a SILModule."); CI.setSILModule(SILModule::createEmptyModule( CI.getMainModule(), CI.getSILOptions(), PerformWMO)); std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create( CI.getASTContext(), CI.getSILModule(), nullptr); if (extendedInfo.isSIB() || DisableSILLinking) SL->getAllForModule(CI.getMainModule()->getName(), nullptr); else SL->getAll(); } // If we're in verify mode, install a custom diagnostic handling for // SourceMgr. if (VerifyMode) enableDiagnosticVerifier(CI.getSourceMgr()); if (OptimizationGroup == OptGroup::Diagnostics) { runSILDiagnosticPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Performance) { runSILOptimizationPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Lowering) { runSILLoweringPasses(*CI.getSILModule()); } else { auto *SILMod = CI.getSILModule(); { auto T = irgen::createIRGenModule(SILMod, getGlobalLLVMContext()); runCommandLineSelectedPasses(SILMod, T.second); irgen::deleteIRGenModule(T); } } if (EmitSIB) { llvm::SmallString<128> OutputFile; if (OutputFilename.size()) { OutputFile = OutputFilename; } else if (ModuleName.size()) { OutputFile = ModuleName; llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } else { OutputFile = CI.getMainModule()->getName().str(); llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } SerializationOptions serializationOpts; serializationOpts.OutputPath = OutputFile.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(CI.getMainModule(), serializationOpts, CI.getSILModule()); } else { const StringRef OutputFile = OutputFilename.size() ? StringRef(OutputFilename) : "-"; if (OutputFile == "-") { CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } else { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None); if (EC) { llvm::errs() << "while opening '" << OutputFile << "': " << EC.message() << '\n'; return 1; } CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } } bool HadError = CI.getASTContext().hadError(); // If we're in -verify mode, we've buffered up all of the generated // diagnostics. Check now to ensure that they meet our expectations. if (VerifyMode) { HadError = verifyDiagnostics(CI.getSourceMgr(), CI.getInputBufferIDs(), /*autoApplyFixes*/false, /*ignoreUnknown*/false); DiagnosticEngine &diags = CI.getDiags(); if (diags.hasFatalErrorOccurred() && !Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) { diags.resetHadAnyError(); diags.diagnose(SourceLoc(), diag::verify_encountered_fatal); HadError = true; } } return HadError; }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, llvm::StringRef Filename, bool IsAST) { assert(!Instance && "Already processing a source file!"); assert(!Filename.empty() && "Unexpected empty filename!"); setCurrentFile(Filename); setCompilerInstance(&CI); // AST files follow a very different path, since they share objects via the // AST unit. if (IsAST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTSupport() && "This action does not have AST support!"); llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics()); std::string Error; ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, Diags); if (!AST) goto failure; setCurrentFile(Filename, AST); // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(&AST->getPreprocessor()); CI.setASTContext(&AST->getASTContext()); // Initialize the action. if (!BeginSourceFileAction(CI, Filename)) goto failure; /// Create the AST consumer. CI.setASTConsumer(CreateASTConsumer(CI, Filename)); if (!CI.hasASTConsumer()) goto failure; return true; } // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); // Initialize the action. if (!BeginSourceFileAction(CI, Filename)) goto failure; /// Create the AST context and consumer unless this is a preprocessor only /// action. if (!usesPreprocessorOnly()) { CI.createASTContext(); CI.setASTConsumer(CreateASTConsumer(CI, Filename)); if (!CI.hasASTConsumer()) goto failure; /// Use PCH? if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { assert(hasPCHSupport() && "This action does not have PCH support!"); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude); if (!CI.getASTContext().getExternalSource()) goto failure; } } // Initialize builtin info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOptions().NoBuiltin); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.takeASTContext(); CI.takePreprocessor(); CI.takeSourceManager(); CI.takeFileManager(); } CI.getDiagnosticClient().EndSourceFile(); setCurrentFile(""); setCompilerInstance(0); return false; }
LLVMResult* ClangCodeContainer::produceModule(Tree signals, const string& filename) { // Compile DSP and generate C code fCompiler->compileMultiSignal(signals); fContainer->produceClass(); #if defined(LLVM_34) || defined(LLVM_35) || defined(LLVM_36) || defined(LLVM_37) || defined(LLVM_38) || defined(LLVM_39) || defined(LLVM_40) // Compile it with 'clang' IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); TextDiagnosticPrinter* DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); Driver TheDriver("", llvm::sys::getProcessTriple(), "a.out", Diags); TheDriver.setTitle("clang interpreter"); int argc = 2; const char* argv[argc + 1]; argv[0] = "clang"; argv[1] = getTempName(); argv[argc] = 0; // NULL terminated argv SmallVector<const char*, 16> Args(argv, argv + argc); Args.push_back("-fsyntax-only"); //Args.push_back("-O3"); Args.push_back("-ffast-math"); list<string>::iterator it; for (it = gGlobal->gImportDirList.begin(); it != gGlobal->gImportDirList.end(); it++) { string path = "-I" + (*it); Args.push_back(strdup(path.c_str())); } OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args)); if (!C) { return NULL; } const driver::JobList &Jobs = C->getJobs(); if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) { SmallString<256> Msg; llvm::raw_svector_ostream OS(Msg); Jobs.Print(OS, "; ", true); Diags.Report(diag::err_fe_expected_compiler_job) << OS.str(); return NULL; } const driver::Command* Cmd = cast<driver::Command>(*Jobs.begin()); if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { Diags.Report(diag::err_fe_expected_clang_command); return NULL; } // Initialize a compiler invocation object from the clang (-cc1) arguments. const driver::ArgStringList &CCArgs = Cmd->getArguments(); OwningPtr<CompilerInvocation> CI(new CompilerInvocation); CompilerInvocation::CreateFromArgs(*CI, const_cast<const char**>(CCArgs.data()), const_cast<const char**>(CCArgs.data()) + CCArgs.size(), Diags); // Create a compiler instance to handle the actual work. CompilerInstance Clang; Clang.setInvocation(CI.take()); // Create the compilers actual diagnostics engine. Clang.createDiagnostics(); if (!Clang.hasDiagnostics()) { return NULL; } CompilerInvocation::setLangDefaults(Clang.getLangOpts(), IK_CXX, LangStandard::lang_unspecified); // Create and execute the frontend to generate an LLVM bitcode module. OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction()); if (!Clang.ExecuteAction(*Act)) { return NULL; } // Get the compiled LLVM module if (llvm::Module* Module = Act->takeModule()) { LLVMResult* result = static_cast<LLVMResult*>(calloc(1, sizeof(LLVMResult))); result->fModule = Module; result->fContext = Act->takeLLVMContext(); // Link LLVM modules defined in 'ffunction' set<string> S; set<string>::iterator f; char error_msg[512]; collectLibrary(S); if (S.size() > 0) { for (f = S.begin(); f != S.end(); f++) { string module_name = unquote(*f); if (endWith(module_name, ".bc") || endWith(module_name, ".ll")) { Module* module = loadModule(module_name, result->fContext); if (module) { bool res = linkModules(result->fModule, module, error_msg); if (!res) printf("Link LLVM modules %s\n", error_msg); } } } } // Possibly link with additional LLVM modules char error[256]; if (!linkAllModules(result->fContext, result->fModule, error)) { stringstream llvm_error; llvm_error << "ERROR : " << error << endl; throw faustexception(llvm_error.str()); } // Keep source files pathnames result->fPathnameList = gGlobal->gReader.listSrcFiles(); // Possibly output file if (filename != "") { std::string err; raw_fd_ostream out(filename.c_str(), err, sysfs_binary_flag); WriteBitcodeToFile(result->fModule, out); } return result; } else { return NULL; } #else return NULL; #endif }
void MacroRepeatedSideEffectsCheck::registerPPCallbacks( CompilerInstance &Compiler) { Compiler.getPreprocessor().addPPCallbacks( ::llvm::make_unique<MacroRepeatedPPCallbacks>( *this, Compiler.getPreprocessor())); }
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef) { // These are classes that trigger generation of a scan method. // Any class that subclasses from one of these classes will // also trigger scan method generation. m_needsScanMethodNames.insert("HPHP::ObjectData"); m_needsScanMethodNames.insert("HPHP::ResourceData"); m_needsScanMethodNames.insert("HPHP::ArrayData"); m_needsScanMethodNames.insert("HPHP::StringData"); m_needsScanMethodNames.insert("HPHP::TypedValue"); m_needsScanMethodNames.insert("HPHP::Cell"); m_needsScanMethodNames.insert("HPHP::RefData"); m_needsScanMethodNames.insert("HPHP::NameValueTable"); m_needsScanMethodNames.insert("HPHP::Array"); m_needsScanMethodNames.insert("HPHP::String"); m_needsScanMethodNames.insert("HPHP::Variant"); m_needsScanMethodNames.insert("HPHP::Object"); m_needsScanMethodNames.insert("HPHP::Resource"); m_needsScanMethodNames.insert("HPHP::req::ptr"); m_needsScanMethodNames.insert("HPHP::LowPtr"); //m_needsScanMethodNames.insert("HPHP::SweepableMember"); //m_needsScanMethodNames.insert("HPHP::RequestEventHandler"); //m_needsScanMethodNames.insert("HPHP::Extension"); // These are classes that have scan methods already defined // by the heap tracer and are ignored when scan generation // happens. // Fundamental types are assumed to have scan methods. // NeedScanMethod types can also appear in this set. // If a particular class causes problems with the scan // generator, you may want to include it in this list and // make sure there is a hand written scan method. m_hasScanMethodNames.insert("HPHP::req::vector"); m_hasScanMethodNames.insert("HPHP::req::dequeue"); m_hasScanMethodNames.insert("HPHP::req::priority_queue"); m_hasScanMethodNames.insert("HPHP::req::flat_map"); m_hasScanMethodNames.insert("HPHP::req::flat_multimap"); m_hasScanMethodNames.insert("HPHP::req::flat_set"); m_hasScanMethodNames.insert("HPHP::req::flat_multiset"); m_hasScanMethodNames.insert("HPHP::req::stack"); m_hasScanMethodNames.insert("HPHP::req::map"); m_hasScanMethodNames.insert("HPHP::req::multimap"); m_hasScanMethodNames.insert("HPHP::req::set"); m_hasScanMethodNames.insert("HPHP::req::multiset"); m_hasScanMethodNames.insert("HPHP::req::hash_map"); m_hasScanMethodNames.insert("HPHP::req::hash_multimap"); m_hasScanMethodNames.insert("HPHP::req::hash_set"); m_hasScanMethodNames.insert("HPHP::req::unique_ptr"); m_hasScanMethodNames.insert("HPHP::req::ptr"); m_hasScanMethodNames.insert("HPHP::AtomicSmartPtr"); m_hasScanMethodNames.insert("HPHP::AtomicSharedPtr"); m_hasScanMethodNames.insert("HPHP::SString"); m_hasScanMethodNames.insert("HPHP::SArray"); m_hasScanMethodNames.insert("HPHP::Array"); m_hasScanMethodNames.insert("HPHP::String"); m_hasScanMethodNames.insert("HPHP::Variant"); m_hasScanMethodNames.insert("HPHP::Object"); m_hasScanMethodNames.insert("HPHP::Resource"); m_hasScanMethodNames.insert("HPHP::ObjectData"); // contains a union m_hasScanMethodNames.insert("HPHP::NameValueTable"); m_hasScanMethodNames.insert("HPHP::NameValueTable::Elm"); m_hasScanMethodNames.insert("HPHP::DummyResource2"); // from test file m_hasScanMethodNames.insert("folly::Optional"); m_hasScanMethodNames.insert("boost::variant"); // These are classes that use non-smart allocation internally. // They should generally not be used to store scanable things. // This list is used to generate warnings. m_badContainerNames.insert("std::vector"); m_badContainerNames.insert("std::map"); m_badContainerNames.insert("std::set"); m_badContainerNames.insert("std::vector"); m_badContainerNames.insert("std::dequeue"); m_badContainerNames.insert("std::priority_queue"); m_badContainerNames.insert("std::flat_map"); m_badContainerNames.insert("std::flat_multimap"); m_badContainerNames.insert("std::flat_set"); m_badContainerNames.insert("std::flat_multiset"); m_badContainerNames.insert("std::stack"); m_badContainerNames.insert("std::map"); m_badContainerNames.insert("std::multimap"); m_badContainerNames.insert("std::set"); m_badContainerNames.insert("std::multiset"); m_badContainerNames.insert("std::hash_map"); m_badContainerNames.insert("std::hash_multimap"); m_badContainerNames.insert("std::hash_set"); m_badContainerNames.insert("std::unique_ptr"); m_badContainerNames.insert("std::shared_ptr"); m_badContainerNames.insert("std::weak_ptr"); // etc. return std::unique_ptr<ASTConsumer>(new AddScanMethodsConsumer( CI.getASTContext(), CI.getSourceManager(), CI.getLangOpts(), m_needsScanMethodNames, m_hasScanMethodNames, m_badContainerNames, m_outdir, m_verbose)); }
std::unique_ptr<ASTConsumer> ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) return CreateASTPrinter(OS, CI.getFrontendOpts().ASTDumpFilter); return nullptr; }
int main(int argc, char *argv[]) { using clang::CompilerInstance; using clang::TargetOptions; using clang::TargetInfo; using clang::FileEntry; using clang::ASTConsumer; using clang::DiagnosticOptions; using clang::TextDiagnosticPrinter; CompilerInstance CI; DiagnosticOptions diagnosticOptions; TextDiagnosticPrinter *pTextDiagnosticPrinter = new TextDiagnosticPrinter( llvm::outs(), diagnosticOptions, true); CI.createDiagnostics(0, NULL, pTextDiagnosticPrinter); TargetOptions targetOptions; targetOptions.Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *pTargetInfo = TargetInfo::CreateTargetInfo( CI.getDiagnostics(), targetOptions); CI.setTarget(pTargetInfo); CI.createFileManager(); CI.createSourceManager(CI.getFileManager()); CI.createPreprocessor(); CI.getPreprocessorOpts().UsePredefines = false; ASTConsumer *astConsumer = new ASTConsumer(); CI.setASTConsumer(astConsumer); CI.createASTContext(); CI.createSema(clang::TU_Complete, NULL); const FileEntry *pFile = CI.getFileManager().getFile(argv[1]); CI.getSourceManager().createMainFileID(pFile); CI.getASTContext().BuiltinInfo.InitializeBuiltins( CI.getPreprocessor().getIdentifierTable(), CI.getLangOpts()); CI.getDiagnosticClient().BeginSourceFile( CI.getLangOpts(), &(CI.getPreprocessor())); clang::ParseAST(CI.getSema()); CI.getDiagnosticClient().EndSourceFile(); return 0; }
bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) { // Find the module map file. const FileEntry *ModuleMap = CI.getFileManager().getFile(Filename); if (!ModuleMap) { CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; return false; } // Parse the module map file. HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); if (HS.loadModuleMapFile(ModuleMap)) return false; if (CI.getLangOpts().CurrentModule.empty()) { CI.getDiagnostics().Report(diag::err_missing_module_name); // FIXME: Eventually, we could consider asking whether there was just // a single module described in the module map, and use that as a // default. Then it would be fairly trivial to just "compile" a module // map with a single module (the common case). return false; } // Dig out the module definition. Module = HS.getModule(CI.getLangOpts().CurrentModule, /*AllowSearch=*/false); if (!Module) { CI.getDiagnostics().Report(diag::err_missing_module) << CI.getLangOpts().CurrentModule << Filename; return false; } // Check whether we can build this module at all. StringRef Feature; if (!Module->isAvailable(CI.getLangOpts(), Feature)) { CI.getDiagnostics().Report(diag::err_module_unavailable) << Module->getFullModuleName() << Feature; return false; } // Do we have an umbrella header for this module? const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader(); // Collect the set of #includes we need to build the module. llvm::SmallString<256> HeaderContents; collectModuleHeaderIncludes(CI.getLangOpts(), CI.getFileManager(), CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module, HeaderContents); if (UmbrellaHeader && HeaderContents.empty()) { // Simple case: we have an umbrella header and there are no additional // includes, we can just parse the umbrella header directly. setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(), getCurrentFileKind())); return true; } FileManager &FileMgr = CI.getFileManager(); llvm::SmallString<128> HeaderName; time_t ModTime; if (UmbrellaHeader) { // Read in the umbrella header. // FIXME: Go through the source manager; the umbrella header may have // been overridden. std::string ErrorStr; llvm::MemoryBuffer *UmbrellaContents = FileMgr.getBufferForFile(UmbrellaHeader, &ErrorStr); if (!UmbrellaContents) { CI.getDiagnostics().Report(diag::err_missing_umbrella_header) << UmbrellaHeader->getName() << ErrorStr; return false; } // Combine the contents of the umbrella header with the automatically- // generated includes. llvm::SmallString<256> OldContents = HeaderContents; HeaderContents = UmbrellaContents->getBuffer(); HeaderContents += "\n\n"; HeaderContents += "/* Module includes */\n"; HeaderContents += OldContents; // Pretend that we're parsing the umbrella header. HeaderName = UmbrellaHeader->getName(); ModTime = UmbrellaHeader->getModificationTime(); delete UmbrellaContents; } else { // Pick an innocuous-sounding name for the umbrella header. HeaderName = Module->Name + ".h"; if (FileMgr.getFile(HeaderName, /*OpenFile=*/false, /*CacheFailure=*/false)) { // Try again! HeaderName = Module->Name + "-module.h"; if (FileMgr.getFile(HeaderName, /*OpenFile=*/false, /*CacheFailure=*/false)) { // Pick something ridiculous and go with it. HeaderName = Module->Name + "-module.hmod"; } } ModTime = time(0); } // Remap the contents of the header name we're using to our synthesized // buffer. const FileEntry *HeaderFile = FileMgr.getVirtualFile(HeaderName, HeaderContents.size(), ModTime); llvm::MemoryBuffer *HeaderContentsBuf = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents); CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf); setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind())); return true; }
int main() { using clang::CompilerInstance; using clang::TargetOptions; using clang::TargetInfo; using clang::FileEntry; using clang::Token; using clang::HeaderSearch; using clang::HeaderSearchOptions; using clang::DiagnosticOptions; using clang::TextDiagnosticPrinter; CompilerInstance ci; DiagnosticOptions diagnosticOptions; ci.createDiagnostics(); llvm::IntrusiveRefCntPtr<TargetOptions> pto( new TargetOptions()); pto->Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto.getPtr()); ci.setTarget(pti); ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); ci.createPreprocessor(); ci.getPreprocessorOpts().UsePredefines = true; llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions> hso( new clang::HeaderSearchOptions()); HeaderSearch headerSearch(hso, ci.getFileManager(), ci.getDiagnostics(), ci.getLangOpts(), pti); // <Warning!!> -- Platform Specific Code lives here // This depends on A) that you're running linux and // B) that you have the same GCC LIBs installed that // I do. // Search through Clang itself for something like this, // go on, you won't find it. The reason why is Clang // has its own versions of std* which are installed under // /usr/local/lib/clang/<version>/include/ // See somewhere around Driver.cpp:77 to see Clang adding // its version of the headers to its include path. hso->AddPath("/usr/include", clang::frontend::Angled, false, false); hso->AddPath("/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include", clang::frontend::Angled, false, false); // </Warning!!> -- End of Platform Specific Code clang::InitializePreprocessor(ci.getPreprocessor(), ci.getPreprocessorOpts(), *hso, ci.getFrontendOpts()); const FileEntry *pFile = ci.getFileManager().getFile("testInclude.c"); ci.getSourceManager().createMainFileID(pFile); ci.getPreprocessor().EnterMainSourceFile(); ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(), &ci.getPreprocessor()); Token tok; do { ci.getPreprocessor().Lex(tok); if( ci.getDiagnostics().hasErrorOccurred()) break; ci.getPreprocessor().DumpToken(tok); std::cerr << std::endl; } while ( tok.isNot(clang::tok::eof)); ci.getDiagnosticClient().EndSourceFile(); return 0; }
void SwiftLangSupport::findInterfaceDocument(StringRef ModuleName, ArrayRef<const char *> Args, std::function<void(const InterfaceDocInfo &)> Receiver) { InterfaceDocInfo Info; CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; if (getASTManager().initCompilerInvocation(Invocation, Args, CI.getDiags(), StringRef(), Error)) { Info.Error = Error; return Receiver(Info); } if (auto IFaceGenRef = IFaceGenContexts.find(ModuleName, Invocation)) Info.ModuleInterfaceName = IFaceGenRef->getDocumentName(); SmallString<128> Buf; SmallVector<std::pair<unsigned, unsigned>, 16> ArgOffs; auto addArgPair = [&](StringRef Arg, StringRef Val) { assert(!Arg.empty()); if (Val.empty()) return; unsigned ArgBegin = Buf.size(); Buf += Arg; unsigned ArgEnd = Buf.size(); unsigned ValBegin = Buf.size(); Buf += Val; unsigned ValEnd = Buf.size(); ArgOffs.push_back(std::make_pair(ArgBegin, ArgEnd)); ArgOffs.push_back(std::make_pair(ValBegin, ValEnd)); }; auto addSingleArg = [&](StringRef Arg) { assert(!Arg.empty()); unsigned ArgBegin = Buf.size(); Buf += Arg; unsigned ArgEnd = Buf.size(); ArgOffs.push_back(std::make_pair(ArgBegin, ArgEnd)); }; addArgPair("-target", Invocation.getTargetTriple()); const auto &SPOpts = Invocation.getSearchPathOptions(); addArgPair("-sdk", SPOpts.SDKPath); for (auto &Path : SPOpts.FrameworkSearchPaths) addArgPair("-F", Path); for (auto &Path : SPOpts.ImportSearchPaths) addArgPair("-I", Path); const auto &ClangOpts = Invocation.getClangImporterOptions(); addArgPair("-module-cache-path", ClangOpts.ModuleCachePath); for (auto &ExtraArg : ClangOpts.ExtraArgs) addArgPair("-Xcc", ExtraArg); if (Invocation.getFrontendOptions().ImportUnderlyingModule) addSingleArg("-import-underlying-module"); addArgPair("-import-objc-header", Invocation.getFrontendOptions().ImplicitObjCHeaderPath); SmallVector<StringRef, 16> NewArgs; for (auto Pair : ArgOffs) { NewArgs.push_back(StringRef(Buf.begin()+Pair.first, Pair.second-Pair.first)); } Info.CompilerArgs = NewArgs; return Receiver(Info); }
int main() { CompilerInstance ci; ci.createDiagnostics(0,NULL); TargetOptions to; to.Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), to); ci.setTarget(pti); ci.getHeaderSearchOpts().AddPath( StringRef("../usr/lib/clang/3.0/include"), frontend::Angled, false, false, false ); ci.getHeaderSearchOpts().AddPath( StringRef("support"), frontend::Quoted, true, false, false ); ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); ci.createPreprocessor(); PrintFunctionsConsumer *astConsumer = new PrintFunctionsConsumer(); ci.setASTConsumer(astConsumer); ci.createASTContext(); const FileEntry *pFile = ci.getFileManager().getFile("julia.h"); ci.getSourceManager().createMainFileID(pFile); ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(), &ci.getPreprocessor()); clang::ParseAST(ci.getPreprocessor(), astConsumer, ci.getASTContext()); ci.getDiagnosticClient().EndSourceFile(); return 0; }
static void reportDocumentStructure(CompilerInstance &CI, EditorConsumer &Consumer) { auto SF = dyn_cast<SourceFile>(CI.getMainModule()->getFiles()[0]); SwiftEditorDocument::reportDocumentStructure(*SF, Consumer); }
int frontend_main(ArrayRef<const char *>Args, const char *Argv0, void *MainAddr) { llvm::InitializeAllTargets(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); CompilerInstance Instance; PrintingDiagnosticConsumer PDC; Instance.addDiagnosticConsumer(&PDC); if (Args.empty()) { Instance.getDiags().diagnose(SourceLoc(), diag::error_no_frontend_args); return 1; } CompilerInvocation Invocation; std::string MainExecutablePath = llvm::sys::fs::getMainExecutable(Argv0, MainAddr); Invocation.setMainExecutablePath(MainExecutablePath); SmallString<128> workingDirectory; llvm::sys::fs::current_path(workingDirectory); // Parse arguments. if (Invocation.parseArgs(Args, Instance.getDiags(), workingDirectory)) { return 1; } if (Invocation.getFrontendOptions().PrintHelp || Invocation.getFrontendOptions().PrintHelpHidden) { unsigned IncludedFlagsBitmask = options::FrontendOption; unsigned ExcludedFlagsBitmask = Invocation.getFrontendOptions().PrintHelpHidden ? 0 : llvm::opt::HelpHidden; std::unique_ptr<llvm::opt::OptTable> Options(createSwiftOptTable()); Options->PrintHelp(llvm::outs(), displayName(MainExecutablePath).c_str(), "Swift frontend", IncludedFlagsBitmask, ExcludedFlagsBitmask); return 0; } if (Invocation.getFrontendOptions().RequestedAction == FrontendOptions::NoneAction) { Instance.getDiags().diagnose(SourceLoc(), diag::error_missing_frontend_action); return 1; } // TODO: reorder, if possible, so that diagnostics emitted during // CompilerInvocation::parseArgs are included in the serialized file. std::unique_ptr<DiagnosticConsumer> SerializedConsumer; { const std::string &SerializedDiagnosticsPath = Invocation.getFrontendOptions().SerializedDiagnosticsPath; if (!SerializedDiagnosticsPath.empty()) { std::error_code EC; std::unique_ptr<llvm::raw_fd_ostream> OS; OS.reset(new llvm::raw_fd_ostream(SerializedDiagnosticsPath, EC, llvm::sys::fs::F_None)); if (EC) { Instance.getDiags().diagnose(SourceLoc(), diag::cannot_open_serialized_file, SerializedDiagnosticsPath, EC.message()); return 1; } SerializedConsumer.reset( serialized_diagnostics::createConsumer(std::move(OS))); Instance.addDiagnosticConsumer(SerializedConsumer.get()); } } std::unique_ptr<DiagnosticConsumer> FixitsConsumer; { const std::string &FixitsOutputPath = Invocation.getFrontendOptions().FixitsOutputPath; if (!FixitsOutputPath.empty()) { std::error_code EC; std::unique_ptr<llvm::raw_fd_ostream> OS; OS.reset(new llvm::raw_fd_ostream(FixitsOutputPath, EC, llvm::sys::fs::F_None)); if (EC) { Instance.getDiags().diagnose(SourceLoc(), diag::cannot_open_file, FixitsOutputPath, EC.message()); return 1; } FixitsConsumer.reset(new JSONFixitWriter(std::move(OS), Invocation.getDiagnosticOptions())); Instance.addDiagnosticConsumer(FixitsConsumer.get()); } } if (Invocation.getDiagnosticOptions().UseColor) PDC.forceColors(); if (Invocation.getFrontendOptions().PrintStats) { llvm::EnableStatistics(); } if (Invocation.getDiagnosticOptions().VerifyDiagnostics) { enableDiagnosticVerifier(Instance.getSourceMgr()); } DependencyTracker depTracker; if (!Invocation.getFrontendOptions().DependenciesFilePath.empty() || !Invocation.getFrontendOptions().ReferenceDependenciesFilePath.empty()) { Instance.setDependencyTracker(&depTracker); } if (Instance.setup(Invocation)) { return 1; } int ReturnValue = 0; bool HadError = performCompile(Instance, Invocation, Args, ReturnValue) || Instance.getASTContext().hadError(); if (!HadError && !Invocation.getFrontendOptions().DumpAPIPath.empty()) { HadError = dumpAPI(Instance.getMainModule(), Invocation.getFrontendOptions().DumpAPIPath); } if (Invocation.getDiagnosticOptions().VerifyDiagnostics) { HadError = verifyDiagnostics(Instance.getSourceMgr(), Instance.getInputBufferIDs()); DiagnosticEngine &diags = Instance.getDiags(); if (diags.hasFatalErrorOccurred() && !Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) { diags.resetHadAnyError(); diags.diagnose(SourceLoc(), diag::verify_encountered_fatal); HadError = true; } } return (HadError ? 1 : ReturnValue); }
/// Performs the compile requested by the user. /// \returns true on error static bool performCompile(CompilerInstance &Instance, CompilerInvocation &Invocation, ArrayRef<const char *> Args, int &ReturnValue) { FrontendOptions opts = Invocation.getFrontendOptions(); FrontendOptions::ActionType Action = opts.RequestedAction; IRGenOptions &IRGenOpts = Invocation.getIRGenOptions(); bool inputIsLLVMIr = Invocation.getInputKind() == InputFileKind::IFK_LLVM_IR; if (inputIsLLVMIr) { auto &LLVMContext = llvm::getGlobalContext(); // Load in bitcode file. assert(Invocation.getInputFilenames().size() == 1 && "We expect a single input for bitcode input!"); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(Invocation.getInputFilenames()[0]); if (!FileBufOrErr) { Instance.getASTContext().Diags.diagnose(SourceLoc(), diag::error_open_input_file, Invocation.getInputFilenames()[0], FileBufOrErr.getError().message()); return true; } llvm::MemoryBuffer *MainFile = FileBufOrErr.get().get(); llvm::SMDiagnostic Err; std::unique_ptr<llvm::Module> Module = llvm::parseIR( MainFile->getMemBufferRef(), Err, LLVMContext); if (!Module) { // TODO: Translate from the diagnostic info to the SourceManager location // if available. Instance.getASTContext().Diags.diagnose(SourceLoc(), diag::error_parse_input_file, Invocation.getInputFilenames()[0], Err.getMessage()); return true; } // TODO: remove once the frontend understands what action it should perform IRGenOpts.OutputKind = getOutputKind(Action); return performLLVM(IRGenOpts, Instance.getASTContext(), Module.get()); } ReferencedNameTracker nameTracker; bool shouldTrackReferences = !opts.ReferenceDependenciesFilePath.empty(); if (shouldTrackReferences) Instance.setReferencedNameTracker(&nameTracker); if (Action == FrontendOptions::DumpParse || Action == FrontendOptions::DumpInterfaceHash) Instance.performParseOnly(); else Instance.performSema(); FrontendOptions::DebugCrashMode CrashMode = opts.CrashMode; if (CrashMode == FrontendOptions::DebugCrashMode::AssertAfterParse) debugFailWithAssertion(); else if (CrashMode == FrontendOptions::DebugCrashMode::CrashAfterParse) debugFailWithCrash(); ASTContext &Context = Instance.getASTContext(); if (Action == FrontendOptions::REPL) { runREPL(Instance, ProcessCmdLine(Args.begin(), Args.end()), Invocation.getParseStdlib()); return false; } SourceFile *PrimarySourceFile = Instance.getPrimarySourceFile(); // We've been told to dump the AST (either after parsing or type-checking, // which is already differentiated in CompilerInstance::performSema()), // so dump or print the main source file and return. if (Action == FrontendOptions::DumpParse || Action == FrontendOptions::DumpAST || Action == FrontendOptions::PrintAST || Action == FrontendOptions::DumpTypeRefinementContexts || Action == FrontendOptions::DumpInterfaceHash) { SourceFile *SF = PrimarySourceFile; if (!SF) { SourceFileKind Kind = Invocation.getSourceFileKind(); SF = &Instance.getMainModule()->getMainSourceFile(Kind); } if (Action == FrontendOptions::PrintAST) SF->print(llvm::outs(), PrintOptions::printEverything()); else if (Action == FrontendOptions::DumpTypeRefinementContexts) SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr); else if (Action == FrontendOptions::DumpInterfaceHash) SF->dumpInterfaceHash(llvm::errs()); else SF->dump(); return false; } // If we were asked to print Clang stats, do so. if (opts.PrintClangStats && Context.getClangModuleLoader()) Context.getClangModuleLoader()->printStatistics(); if (!opts.DependenciesFilePath.empty()) (void)emitMakeDependencies(Context.Diags, *Instance.getDependencyTracker(), opts); if (shouldTrackReferences) emitReferenceDependencies(Context.Diags, Instance.getPrimarySourceFile(), *Instance.getDependencyTracker(), opts); if (Context.hadError()) return true; // FIXME: This is still a lousy approximation of whether the module file will // be externally consumed. bool moduleIsPublic = !Instance.getMainModule()->hasEntryPoint() && opts.ImplicitObjCHeaderPath.empty() && !Context.LangOpts.EnableAppExtensionRestrictions; // We've just been told to perform a parse, so we can return now. if (Action == FrontendOptions::Parse) { if (!opts.ObjCHeaderOutputPath.empty()) return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic); return false; } assert(Action >= FrontendOptions::EmitSILGen && "All actions not requiring SILGen must have been handled!"); std::unique_ptr<SILModule> SM = Instance.takeSILModule(); if (!SM) { if (opts.PrimaryInput.hasValue() && opts.PrimaryInput.getValue().isFilename()) { FileUnit *PrimaryFile = PrimarySourceFile; if (!PrimaryFile) { auto Index = opts.PrimaryInput.getValue().Index; PrimaryFile = Instance.getMainModule()->getFiles()[Index]; } SM = performSILGeneration(*PrimaryFile, Invocation.getSILOptions(), None, opts.SILSerializeAll); } else { SM = performSILGeneration(Instance.getMainModule(), Invocation.getSILOptions(), opts.SILSerializeAll, true); } } // We've been told to emit SIL after SILGen, so write it now. if (Action == FrontendOptions::EmitSILGen) { // If we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL, opts.getSingleOutputFilename(), opts.EmitSortedSIL); } if (Action == FrontendOptions::EmitSIBGen) { // If we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance.getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(DC, serializationOpts, SM.get()); } return false; } // Perform "stable" optimizations that are invariant across compiler versions. if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses && runSILDiagnosticPasses(*SM)) return true; // Now if we are asked to link all, link all. if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll) performSILLinking(SM.get(), true); SM->verify(); // Perform SIL optimization passes if optimizations haven't been disabled. // These may change across compiler versions. if (IRGenOpts.Optimize) { StringRef CustomPipelinePath = Invocation.getSILOptions().ExternalPassPipelineFilename; if (!CustomPipelinePath.empty()) { runSILOptimizationPassesWithFileSpecification(*SM, CustomPipelinePath); } else { runSILOptimizationPasses(*SM); } } else { runSILPassesForOnone(*SM); } SM->verify(); // Gather instruction counts if we are asked to do so. if (SM->getOptions().PrintInstCounts) { performSILInstCount(&*SM); } // Get the main source file's private discriminator and attach it to // the compile unit's flags. if (PrimarySourceFile) { Identifier PD = PrimarySourceFile->getPrivateDiscriminator(); if (!PD.empty()) IRGenOpts.DWARFDebugFlags += (" -private-discriminator "+PD.str()).str(); } if (!opts.ObjCHeaderOutputPath.empty()) { (void)printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic); } if (Action == FrontendOptions::EmitSIB) { auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance.getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(DC, serializationOpts, SM.get()); } return false; } if (!opts.ModuleOutputPath.empty() || !opts.ModuleDocOutputPath.empty()) { auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) : Instance.getMainModule(); if (!opts.ModuleOutputPath.empty()) { SerializationOptions serializationOpts; serializationOpts.OutputPath = opts.ModuleOutputPath.c_str(); serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str(); serializationOpts.SerializeAllSIL = opts.SILSerializeAll; if (opts.SerializeBridgingHeader) serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath; serializationOpts.ModuleLinkName = opts.ModuleLinkName; serializationOpts.ExtraClangOptions = Invocation.getClangImporterOptions().ExtraArgs; if (!IRGenOpts.ForceLoadSymbolName.empty()) serializationOpts.AutolinkForceLoad = true; // Options contain information about the developer's computer, // so only serialize them if the module isn't going to be shipped to // the public. serializationOpts.SerializeOptionsForDebugging = !moduleIsPublic || opts.AlwaysSerializeDebuggingOptions; serialize(DC, serializationOpts, SM.get()); } if (Action == FrontendOptions::EmitModuleOnly) return false; } assert(Action >= FrontendOptions::EmitSIL && "All actions not requiring SILPasses must have been handled!"); // We've been told to write canonical SIL, so write it now. if (Action == FrontendOptions::EmitSIL) { return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL, opts.getSingleOutputFilename(), opts.EmitSortedSIL); } assert(Action >= FrontendOptions::Immediate && "All actions not requiring IRGen must have been handled!"); assert(Action != FrontendOptions::REPL && "REPL mode must be handled immediately after Instance.performSema()"); // Check if we had any errors; if we did, don't proceed to IRGen. if (Context.hadError()) return true; // Cleanup instructions/builtin calls not suitable for IRGen. performSILCleanup(SM.get()); // TODO: remove once the frontend understands what action it should perform IRGenOpts.OutputKind = getOutputKind(Action); if (Action == FrontendOptions::Immediate) { assert(!PrimarySourceFile && "-i doesn't work in -primary-file mode"); IRGenOpts.UseJIT = true; IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::Normal; const ProcessCmdLine &CmdLine = ProcessCmdLine(opts.ImmediateArgv.begin(), opts.ImmediateArgv.end()); Instance.setSILModule(std::move(SM)); ReturnValue = RunImmediately(Instance, CmdLine, IRGenOpts, Invocation.getSILOptions()); return false; } // FIXME: We shouldn't need to use the global context here, but // something is persisting across calls to performIRGeneration. auto &LLVMContext = llvm::getGlobalContext(); if (PrimarySourceFile) { performIRGeneration(IRGenOpts, *PrimarySourceFile, SM.get(), opts.getSingleOutputFilename(), LLVMContext); } else { performIRGeneration(IRGenOpts, Instance.getMainModule(), SM.get(), opts.getSingleOutputFilename(), LLVMContext); } return false; }
bool ModifyAction::BeginInvocation(CompilerInstance &CI) { return !arcmt::applyTransformations(CI.getInvocation(), getCurrentInput(), CI.getDiagnostics().getClient()); }
bool swift::immediate::IRGenImportedModules( CompilerInstance &CI, llvm::Module &Module, llvm::SmallPtrSet<swift::Module *, 8> &ImportedModules, SmallVectorImpl<llvm::Function*> &InitFns, IRGenOptions &IRGenOpts, const SILOptions &SILOpts) { swift::Module *M = CI.getMainModule(); // Perform autolinking. SmallVector<LinkLibrary, 4> AllLinkLibraries(IRGenOpts.LinkLibraries); auto addLinkLibrary = [&](LinkLibrary linkLib) { AllLinkLibraries.push_back(linkLib); }; M->forAllVisibleModules({}, /*includePrivateTopLevel=*/true, [&](Module::ImportedModule import) { import.second->collectLinkLibraries(addLinkLibrary); }); // Hack to handle thunks eagerly synthesized by the Clang importer. swift::Module *prev = nullptr; for (auto external : CI.getASTContext().ExternalDefinitions) { swift::Module *next = external->getModuleContext(); if (next == prev) continue; next->collectLinkLibraries(addLinkLibrary); prev = next; } tryLoadLibraries(AllLinkLibraries, CI.getASTContext().SearchPathOpts, CI.getDiags()); ImportedModules.insert(M); if (!CI.hasSourceImport()) return false; // IRGen the modules this module depends on. This is only really necessary // for imported source, but that's a very convenient thing to do in -i mode. // FIXME: Crawling all loaded modules is a hack. // FIXME: And re-doing SILGen, SIL-linking, SIL diagnostics, and IRGen is // expensive, because it's not properly being limited to new things right now. bool hadError = false; for (auto &entry : CI.getASTContext().LoadedModules) { swift::Module *import = entry.second; if (!ImportedModules.insert(import).second) continue; std::unique_ptr<SILModule> SILMod = performSILGeneration(import, CI.getSILOptions()); performSILLinking(SILMod.get()); if (runSILDiagnosticPasses(*SILMod)) { hadError = true; break; } // FIXME: We shouldn't need to use the global context here, but // something is persisting across calls to performIRGeneration. auto SubModule = performIRGeneration(IRGenOpts, import, SILMod.get(), import->getName().str(), llvm::getGlobalContext()); if (CI.getASTContext().hadError()) { hadError = true; break; } if (!linkLLVMModules(&Module, std::move(SubModule) // TODO: reactivate the linker mode if it is // supported in llvm again. Otherwise remove the // commented code completely. /*, llvm::Linker::DestroySource */)) { hadError = true; break; } // FIXME: This is an ugly hack; need to figure out how this should // actually work. SmallVector<char, 20> NameBuf; StringRef InitFnName = (import->getName().str() + ".init").toStringRef(NameBuf); llvm::Function *InitFn = Module.getFunction(InitFnName); if (InitFn) InitFns.push_back(InitFn); } return hadError; }
bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) { // Find the module map file. const FileEntry *ModuleMap = CI.getFileManager().getFile(Filename); if (!ModuleMap) { CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; return false; } // Parse the module map file. HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); if (HS.loadModuleMapFile(ModuleMap, IsSystem)) return false; if (CI.getLangOpts().CurrentModule.empty()) { CI.getDiagnostics().Report(diag::err_missing_module_name); // FIXME: Eventually, we could consider asking whether there was just // a single module described in the module map, and use that as a // default. Then it would be fairly trivial to just "compile" a module // map with a single module (the common case). return false; } // If we're being run from the command-line, the module build stack will not // have been filled in yet, so complete it now in order to allow us to detect // module cycles. SourceManager &SourceMgr = CI.getSourceManager(); if (SourceMgr.getModuleBuildStack().empty()) SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, FullSourceLoc(SourceLocation(), SourceMgr)); // Dig out the module definition. Module = HS.lookupModule(CI.getLangOpts().CurrentModule, /*AllowSearch=*/false); if (!Module) { CI.getDiagnostics().Report(diag::err_missing_module) << CI.getLangOpts().CurrentModule << Filename; return false; } // Check whether we can build this module at all. clang::Module::Requirement Requirement; clang::Module::UnresolvedHeaderDirective MissingHeader; if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement, MissingHeader)) { if (MissingHeader.FileNameLoc.isValid()) { CI.getDiagnostics().Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) << MissingHeader.IsUmbrella << MissingHeader.FileName; } else { CI.getDiagnostics().Report(diag::err_module_unavailable) << Module->getFullModuleName() << Requirement.second << Requirement.first; } return false; } if (ModuleMapForUniquing && ModuleMapForUniquing != ModuleMap) { Module->IsInferred = true; HS.getModuleMap().setInferredModuleAllowedBy(Module, ModuleMapForUniquing); } else { ModuleMapForUniquing = ModuleMap; } FileManager &FileMgr = CI.getFileManager(); // Collect the set of #includes we need to build the module. SmallString<256> HeaderContents; std::error_code Err = std::error_code(); if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) // FIXME: Track the file name as written. Err = addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(), Module->IsExternC); if (!Err) Err = collectModuleHeaderIncludes( CI.getLangOpts(), FileMgr, CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module, HeaderContents); if (Err) { CI.getDiagnostics().Report(diag::err_module_cannot_create_includes) << Module->getFullModuleName() << Err.message(); return false; } // Inform the preprocessor that includes from within the input buffer should // be resolved relative to the build directory of the module map file. CI.getPreprocessor().setMainFileDir(Module->Directory); std::unique_ptr<llvm::MemoryBuffer> InputBuffer = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents, Module::getModuleInputBufferName()); // Ownership of InputBuffer will be transferred to the SourceManager. setCurrentInput(FrontendInputFile(InputBuffer.release(), getCurrentFileKind(), Module->IsSystem)); return true; }
int swift::RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine, IRGenOptions &IRGenOpts, const SILOptions &SILOpts) { ASTContext &Context = CI.getASTContext(); // IRGen the main module. auto *swiftModule = CI.getMainModule(); // FIXME: We shouldn't need to use the global context here, but // something is persisting across calls to performIRGeneration. auto ModuleOwner = performIRGeneration( IRGenOpts, swiftModule, CI.getSILModule(), swiftModule->getName().str(), llvm::getGlobalContext()); auto *Module = ModuleOwner.get(); if (Context.hadError()) return -1; SmallVector<llvm::Function*, 8> InitFns; llvm::SmallPtrSet<swift::Module *, 8> ImportedModules; if (IRGenImportedModules(CI, *Module, ImportedModules, InitFns, IRGenOpts, SILOpts)) return -1; llvm::PassManagerBuilder PMBuilder; PMBuilder.OptLevel = 2; PMBuilder.Inliner = llvm::createFunctionInliningPass(200); if (!loadSwiftRuntime(Context.SearchPathOpts.RuntimeLibraryPath)) { CI.getDiags().diagnose(SourceLoc(), diag::error_immediate_mode_missing_stdlib); return -1; } // Build the ExecutionEngine. llvm::EngineBuilder builder(std::move(ModuleOwner)); std::string ErrorMsg; llvm::TargetOptions TargetOpt; std::string CPU; std::vector<std::string> Features; std::tie(TargetOpt, CPU, Features) = getIRTargetOptions(IRGenOpts, swiftModule->getASTContext()); builder.setRelocationModel(llvm::Reloc::PIC_); builder.setTargetOptions(TargetOpt); builder.setMCPU(CPU); builder.setMAttrs(Features); builder.setErrorStr(&ErrorMsg); builder.setEngineKind(llvm::EngineKind::JIT); llvm::ExecutionEngine *EE = builder.create(); if (!EE) { llvm::errs() << "Error loading JIT: " << ErrorMsg; return -1; } DEBUG(llvm::dbgs() << "Module to be executed:\n"; Module->dump()); EE->finalizeObject(); // Run the generated program. for (auto InitFn : InitFns) { DEBUG(llvm::dbgs() << "Running initialization function " << InitFn->getName() << '\n'); EE->runFunctionAsMain(InitFn, CmdLine, 0); } DEBUG(llvm::dbgs() << "Running static constructors\n"); EE->runStaticConstructorsDestructors(false); DEBUG(llvm::dbgs() << "Running main\n"); llvm::Function *EntryFn = Module->getFunction("main"); return EE->runFunctionAsMain(EntryFn, CmdLine, 0); }
std::unique_ptr<ASTConsumer> ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter, CI.getFrontendOpts().ASTDumpDecls, CI.getFrontendOpts().ASTDumpLookups); }
std::unique_ptr<ASTConsumer> CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { BackendAction BA = static_cast<BackendAction>(Act); raw_pwrite_stream *OS = GetOutputStream(CI, InFile, BA); if (BA != Backend_EmitNothing && !OS) return nullptr; llvm::Module *LinkModuleToUse = LinkModule; // If we were not given a link module, and the user requested that one be // loaded from bitcode, do so now. const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile; if (!LinkModuleToUse && !LinkBCFile.empty()) { auto BCBuf = CI.getFileManager().getBufferForFile(LinkBCFile); if (!BCBuf) { CI.getDiagnostics().Report(diag::err_cannot_open_file) << LinkBCFile << BCBuf.getError().message(); return nullptr; } ErrorOr<std::unique_ptr<llvm::Module>> ModuleOrErr = getLazyBitcodeModule(std::move(*BCBuf), *VMContext); if (std::error_code EC = ModuleOrErr.getError()) { CI.getDiagnostics().Report(diag::err_cannot_open_file) << LinkBCFile << EC.message(); return nullptr; } LinkModuleToUse = ModuleOrErr.get().release(); } CoverageSourceInfo *CoverageInfo = nullptr; // Add the preprocessor callback only when the coverage mapping is generated. if (CI.getCodeGenOpts().CoverageMapping) { CoverageInfo = new CoverageSourceInfo; CI.getPreprocessor().addPPCallbacks( std::unique_ptr<PPCallbacks>(CoverageInfo)); } std::unique_ptr<BackendConsumer> Result(new BackendConsumer( BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModuleToUse, OS, *VMContext, CoverageInfo)); BEConsumer = Result.get(); return std::move(Result); }
/// \brief Compile a module file for the given module, using the options /// provided by the importing compiler instance. static void compileModule(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName) { llvm::LockFileManager Locked(ModuleFileName); switch (Locked) { case llvm::LockFileManager::LFS_Error: return; case llvm::LockFileManager::LFS_Owned: // We're responsible for building the module ourselves. Do so below. break; case llvm::LockFileManager::LFS_Shared: // Someone else is responsible for building the module. Wait for them to // finish. Locked.waitForUnlock(); return; } ModuleMap &ModMap = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); // Construct a compiler invocation for creating this module. IntrusiveRefCntPtr<CompilerInvocation> Invocation (new CompilerInvocation(ImportingInstance.getInvocation())); PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); // For any options that aren't intended to affect how a module is built, // reset them to their default values. Invocation->getLangOpts()->resetNonModularOptions(); PPOpts.resetNonModularOptions(); // Note the name of the module we're building. Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName(); // Make sure that the failed-module structure has been allocated in // the importing instance, and propagate the pointer to the newly-created // instance. PreprocessorOptions &ImportingPPOpts = ImportingInstance.getInvocation().getPreprocessorOpts(); if (!ImportingPPOpts.FailedModules) ImportingPPOpts.FailedModules = new PreprocessorOptions::FailedModulesSet; PPOpts.FailedModules = ImportingPPOpts.FailedModules; // If there is a module map file, build the module using the module map. // Set up the inputs/outputs so that we build the module from its umbrella // header. FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); FrontendOpts.OutputFile = ModuleFileName.str(); FrontendOpts.DisableFree = false; FrontendOpts.Inputs.clear(); InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); // Get or create the module map that we'll use to build this module. SmallString<128> TempModuleMapFileName; if (const FileEntry *ModuleMapFile = ModMap.getContainingModuleMapFile(Module)) { // Use the module map where this module resides. FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), IK)); } else { // Create a temporary module map file. TempModuleMapFileName = Module->Name; TempModuleMapFileName += "-%%%%%%%%.map"; int FD; if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, TempModuleMapFileName, /*makeAbsolute=*/true) != llvm::errc::success) { ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file) << TempModuleMapFileName; return; } // Print the module map to this file. llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); Module->print(OS); FrontendOpts.Inputs.push_back( FrontendInputFile(TempModuleMapFileName.str().str(), IK)); } // Don't free the remapped file buffers; they are owned by our caller. PPOpts.RetainRemappedFileBuffers = true; Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; assert(ImportingInstance.getInvocation().getModuleHash() == Invocation->getModuleHash() && "Module hash mismatch!"); // Construct a compiler instance that will be used to actually create the // module. CompilerInstance Instance; Instance.setInvocation(&*Invocation); Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, &ImportingInstance.getDiagnosticClient(), /*ShouldOwnClient=*/true, /*ShouldCloneClient=*/true); // Note that this module is part of the module build stack, so that we // can detect cycles in the module graph. Instance.createFileManager(); // FIXME: Adopt file manager from importer? Instance.createSourceManager(Instance.getFileManager()); SourceManager &SourceMgr = Instance.getSourceManager(); SourceMgr.setModuleBuildStack( ImportingInstance.getSourceManager().getModuleBuildStack()); SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(), FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); // Construct a module-generating action. GenerateModuleAction CreateModuleAction; // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. const unsigned ThreadStackSize = 8 << 20; llvm::CrashRecoveryContext CRC; CompileModuleMapData Data = { Instance, CreateModuleAction }; CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); // Delete the temporary module map file. // FIXME: Even though we're executing under crash protection, it would still // be nice to do this with RemoveFileOnSignal when we can. However, that // doesn't make sense for all clients, so clean this up manually. Instance.clearOutputFiles(/*EraseFiles=*/true); if (!TempModuleMapFileName.empty()) llvm::sys::Path(TempModuleMapFileName).eraseFromDisk(); }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); assert(!Input.isEmpty() && "Unexpected empty filename!"); setCurrentInput(Input); setCompilerInstance(&CI); StringRef InputFile = Input.getFile(); bool HasBegunSourceFile = false; if (!BeginInvocation(CI)) goto failure; // AST files follow a very different path, since they share objects via the // AST unit. if (Input.getKind() == IK_AST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTFileSupport() && "This action does not have AST file support!"); IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); ASTUnit *AST = ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts()); if (!AST) goto failure; setCurrentInput(Input, AST); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(&AST->getPreprocessor()); CI.setASTContext(&AST->getASTContext()); // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST consumer. CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); if (!CI.hasASTConsumer()) goto failure; return true; } // Set up the file and source managers, if needed. if (!CI.hasFileManager()) CI.createFileManager(); if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); // IR files bypass the rest of initialization. if (Input.getKind() == IK_LLVM_IR) { assert(hasIRSupport() && "This action does not have IR file support!"); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; return true; } // If the implicit PCH include is actually a directory, rather than // a single file, search for a suitable PCH file in that directory. if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { FileManager &FileMgr = CI.getFileManager(); PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); StringRef PCHInclude = PPOpts.ImplicitPCHInclude; if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { llvm::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts())) { PPOpts.ImplicitPCHInclude = Dir->path(); Found = true; break; } } if (!Found) { CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; return true; } } } // Set up the preprocessor. CI.createPreprocessor(); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { CI.createASTContext(); OwningPtr<ASTConsumer> Consumer( CreateWrappedASTConsumer(CI, InputFile)); if (!Consumer) goto failure; CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. OwningPtr<ExternalASTSource> source; source.reset(ChainedIncludesSource::create(CI)); if (!source) goto failure; CI.setModuleManager(static_cast<ASTReader*>( &static_cast<ChainedIncludesSource*>(source.get())->getFinalReader())); CI.getASTContext().setExternalSource(source); } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { // Use PCH. assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = Consumer->GetASTDeserializationListener(); if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) DeserialListener = new DeserializedDeclsDumper(DeserialListener); if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, DeserialListener); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener); if (!CI.getASTContext().getExternalSource()) goto failure; } CI.setASTConsumer(Consumer.take()); if (!CI.hasASTConsumer()) goto failure; } // Initialize built-in info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); } // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { OwningPtr<ExternalASTSource> Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.setASTContext(0); CI.setPreprocessor(0); CI.setSourceManager(0); CI.setFileManager(0); } if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); CI.clearOutputFiles(/*EraseFiles=*/true); setCurrentInput(FrontendInputFile()); setCompilerInstance(0); return false; }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); assert(!Input.isEmpty() && "Unexpected empty filename!"); setCurrentInput(Input); setCompilerInstance(&CI); StringRef InputFile = Input.getFile(); bool HasBegunSourceFile = false; if (!BeginInvocation(CI)) goto failure; // AST files follow a very different path, since they share objects via the // AST unit. if (Input.getKind() == IK_AST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTFileSupport() && "This action does not have AST file support!"); IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( InputFile, CI.getPCHContainerReader(), Diags, CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs); if (!AST) goto failure; // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr); HasBegunSourceFile = true; // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(AST->getPreprocessorPtr()); CI.setASTContext(&AST->getASTContext()); setCurrentInput(Input, std::move(AST)); // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST consumer. CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); if (!CI.hasASTConsumer()) goto failure; return true; } if (!CI.hasVirtualFileSystem()) { if (IntrusiveRefCntPtr<vfs::FileSystem> VFS = createVFSFromCompilerInvocation(CI.getInvocation(), CI.getDiagnostics())) CI.setVirtualFileSystem(VFS); else goto failure; } // Set up the file and source managers, if needed. if (!CI.hasFileManager()) CI.createFileManager(); if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); // IR files bypass the rest of initialization. if (Input.getKind() == IK_LLVM_IR) { assert(hasIRSupport() && "This action does not have IR file support!"); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Initialize the main file entry. if (!CI.InitializeSourceManager(CurrentInput)) goto failure; return true; } // If the implicit PCH include is actually a directory, rather than // a single file, search for a suitable PCH file in that directory. if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { FileManager &FileMgr = CI.getFileManager(); PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); StringRef PCHInclude = PPOpts.ImplicitPCHInclude; std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath(); if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { std::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. if (ASTReader::isAcceptableASTFile( Dir->getName(), FileMgr, CI.getPCHContainerReader(), CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(), SpecificModuleCachePath)) { PPOpts.ImplicitPCHInclude = Dir->getName(); Found = true; break; } } if (!Found) { CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; goto failure; } } } // Set up the preprocessor if needed. When parsing model files the // preprocessor of the original source is reused. if (!isModelParsingAction()) CI.createPreprocessor(getTranslationUnitKind()); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Initialize the main file entry. It is important that this occurs after // BeginSourceFileAction, which may change CurrentInput during module builds. if (!CI.InitializeSourceManager(CurrentInput)) goto failure; // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { // Parsing a model file should reuse the existing ASTContext. if (!isModelParsingAction()) CI.createASTContext(); std::unique_ptr<ASTConsumer> Consumer = CreateWrappedASTConsumer(CI, InputFile); if (!Consumer) goto failure; // FIXME: should not overwrite ASTMutationListener when parsing model files? if (!isModelParsingAction()) CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader; source = createChainedIncludesSource(CI, FinalReader); if (!source) goto failure; CI.setModuleManager(static_cast<ASTReader *>(FinalReader.get())); CI.getASTContext().setExternalSource(source); } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { // Use PCH. assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = Consumer->GetASTDeserializationListener(); bool DeleteDeserialListener = false; if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) { DeserialListener = new DeserializedDeclsDumper(DeserialListener, DeleteDeserialListener); DeleteDeserialListener = true; } if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) { DeserialListener = new DeserializedDeclsChecker( CI.getASTContext(), CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, DeserialListener, DeleteDeserialListener); DeleteDeserialListener = true; } CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener, DeleteDeserialListener); if (!CI.getASTContext().getExternalSource()) goto failure; } CI.setASTConsumer(std::move(Consumer)); if (!CI.hasASTConsumer()) goto failure; } // Initialize built-in info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); // If modules are enabled, create the module manager before creating // any builtins, so that all declarations know that they might be // extended by an external source. if (CI.getLangOpts().Modules) CI.createModuleManager(); PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); } else { // FIXME: If this is a problem, recover from it by creating a multiplex // source. assert((!CI.getLangOpts().Modules || CI.getModuleManager()) && "modules enabled but created an external source that " "doesn't support modules"); } // If we were asked to load any module map files, do so now. for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { if (auto *File = CI.getFileManager().getFile(Filename)) CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( File, /*IsSystem*/false); else CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; } // If we were asked to load any module files, do so now. for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) if (!CI.loadModuleFile(ModuleFile)) goto failure; // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { IntrusiveRefCntPtr<ExternalASTSource> Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.setASTContext(nullptr); CI.setPreprocessor(nullptr); CI.setSourceManager(nullptr); CI.setFileManager(nullptr); } if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); CI.clearOutputFiles(/*EraseFiles=*/true); setCurrentInput(FrontendInputFile()); setCompilerInstance(nullptr); return false; }
CompilerInstance* CIFactory::createCI(llvm::MemoryBuffer* buffer, int argc, const char* const *argv, const char* llvmdir) { // Create an instance builder, passing the llvmdir and arguments. // // Initialize the llvm library. llvm::InitializeNativeTarget(); llvm::InitializeAllAsmPrinters(); llvm::sys::Path resource_path; if (llvmdir) { resource_path = llvmdir; resource_path.appendComponent("lib"); resource_path.appendComponent("clang"); resource_path.appendComponent(CLANG_VERSION_STRING); } else { // FIXME: The first arg really does need to be argv[0] on FreeBSD. // // Note: The second arg is not used for Apple, FreeBSD, Linux, // or cygwin, and can only be used on systems which support // the use of dladdr(). // // Note: On linux and cygwin this uses /proc/self/exe to find the path. // // Note: On Apple it uses _NSGetExecutablePath(). // // Note: On FreeBSD it uses getprogpath(). // // Note: Otherwise it uses dladdr(). // resource_path = CompilerInvocation::GetResourcesPath("cling", (void*)(intptr_t) locate_cling_executable ); } if (!resource_path.canRead()) { llvm::errs() << "ERROR in cling::CIFactory::createCI():\n resource directory " << resource_path.str() << " not found!\n"; resource_path = ""; } //______________________________________ DiagnosticOptions* DefaultDiagnosticOptions = new DiagnosticOptions(); DefaultDiagnosticOptions->ShowColors = llvm::sys::Process::StandardErrHasColors() ? 1 : 0; TextDiagnosticPrinter* DiagnosticPrinter = new TextDiagnosticPrinter(llvm::errs(), DefaultDiagnosticOptions); llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(new DiagnosticIDs()); DiagnosticsEngine* Diagnostics = new DiagnosticsEngine(DiagIDs, DefaultDiagnosticOptions, DiagnosticPrinter, /*Owns it*/ true); // LEAKS! std::vector<const char*> argvCompile(argv, argv + argc); // We do C++ by default; append right after argv[0] name // Only insert it if there is no other "-x": bool haveMinusX = false; for (const char* const* iarg = argv; !haveMinusX && iarg < argv + argc; ++iarg) { haveMinusX = !strcmp(*iarg, "-x"); } if (!haveMinusX) { argvCompile.insert(argvCompile.begin() + 1,"-x"); argvCompile.insert(argvCompile.begin() + 2, "c++"); } argvCompile.push_back("-c"); argvCompile.push_back("-"); clang::driver::Driver Driver(argv[0], llvm::sys::getDefaultTargetTriple(), "cling.out", *Diagnostics); //Driver.setWarnMissingInput(false); Driver.setCheckInputsExist(false); // think foo.C(12) llvm::ArrayRef<const char*>RF(&(argvCompile[0]), argvCompile.size()); llvm::OwningPtr<clang::driver::Compilation> Compilation(Driver.BuildCompilation(RF)); const clang::driver::ArgStringList* CC1Args = GetCC1Arguments(Diagnostics, Compilation.get()); if (CC1Args == NULL) { return 0; } clang::CompilerInvocation* Invocation = new clang::CompilerInvocation; clang::CompilerInvocation::CreateFromArgs(*Invocation, CC1Args->data() + 1, CC1Args->data() + CC1Args->size(), *Diagnostics); Invocation->getFrontendOpts().DisableFree = true; if (Invocation->getHeaderSearchOpts().UseBuiltinIncludes && !resource_path.empty()) { // Update ResourceDir // header search opts' entry for resource_path/include isn't // updated by providing a new resource path; update it manually. clang::HeaderSearchOptions& Opts = Invocation->getHeaderSearchOpts(); llvm::sys::Path oldResInc(Opts.ResourceDir); oldResInc.appendComponent("include"); llvm::sys::Path newResInc(resource_path); newResInc.appendComponent("include"); bool foundOldResInc = false; for (unsigned i = 0, e = Opts.UserEntries.size(); !foundOldResInc && i != e; ++i) { HeaderSearchOptions::Entry &E = Opts.UserEntries[i]; if (!E.IsFramework && E.Group == clang::frontend::System && E.IgnoreSysRoot && oldResInc.str() == E.Path) { E.Path = newResInc.str(); foundOldResInc = true; } } Opts.ResourceDir = resource_path.str(); } // Create and setup a compiler instance. CompilerInstance* CI = new CompilerInstance(); CI->setInvocation(Invocation); CI->createDiagnostics(DiagnosticPrinter, /*ShouldOwnClient=*/ false, /*ShouldCloneClient=*/ false); { // // Buffer the error messages while we process // the compiler options. // // Set the language options, which cling needs SetClingCustomLangOpts(CI->getLangOpts()); CI->getInvocation().getPreprocessorOpts().addMacroDef("__CLING__"); if (CI->getLangOpts().CPlusPlus11 == 1) { // http://llvm.org/bugs/show_bug.cgi?id=13530 CI->getInvocation().getPreprocessorOpts() .addMacroDef("__CLING__CXX11"); } if (CI->getDiagnostics().hasErrorOccurred()) { delete CI; CI = 0; return 0; } } CI->setTarget(TargetInfo::CreateTargetInfo(CI->getDiagnostics(), &Invocation->getTargetOpts())); if (!CI->hasTarget()) { delete CI; CI = 0; return 0; } CI->getTarget().setForcedLangOptions(CI->getLangOpts()); SetClingTargetLangOpts(CI->getLangOpts(), CI->getTarget()); if (CI->getTarget().getTriple().getOS() == llvm::Triple::Cygwin) { // clang "forgets" the basic arch part needed by winnt.h: if (CI->getTarget().getTriple().getArch() == llvm::Triple::x86) { CI->getInvocation().getPreprocessorOpts().addMacroDef("_X86_=1"); } else if (CI->getTarget().getTriple().getArch() == llvm::Triple::x86_64) { CI->getInvocation().getPreprocessorOpts().addMacroDef("__x86_64=1"); } else { llvm::errs() << "Warning: unhandled target architecture " << CI->getTarget().getTriple().getArchName() << '\n'; } } // Set up source and file managers CI->createFileManager(); SourceManager* SM = new SourceManager(CI->getDiagnostics(), CI->getFileManager(), /*UserFilesAreVolatile*/ true); CI->setSourceManager(SM); // FIXME: SM leaks. // Set up the memory buffer if (buffer) CI->getSourceManager().createMainFileIDForMemBuffer(buffer); else { // As main file we want // * a virtual file that is claiming to be huge // * with an empty memory buffer attached (to bring the content) SourceManager& SM = CI->getSourceManager(); FileManager& FM = SM.getFileManager(); // Build the virtual file const char* Filename = "InteractiveInputLineIncluder.h"; const std::string& CGOptsMainFileName = CI->getInvocation().getCodeGenOpts().MainFileName; if (!CGOptsMainFileName.empty()) Filename = CGOptsMainFileName.c_str(); const FileEntry* FE = FM.getVirtualFile(Filename, 1U << 15U, time(0)); FileID MainFileID = SM.createMainFileID(FE, SrcMgr::C_User); const SrcMgr::SLocEntry& MainFileSLocE = SM.getSLocEntry(MainFileID); const SrcMgr::ContentCache* MainFileCC = MainFileSLocE.getFile().getContentCache(); llvm::MemoryBuffer* MainFileMB = llvm::MemoryBuffer::getMemBuffer("/*CLING MAIN FILE*/\n"); const_cast<SrcMgr::ContentCache*>(MainFileCC)->setBuffer(MainFileMB); } // Set up the preprocessor CI->createPreprocessor(); Preprocessor& PP = CI->getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); // Set up the ASTContext ASTContext *Ctx = new ASTContext(CI->getLangOpts(), PP.getSourceManager(), &CI->getTarget(), PP.getIdentifierTable(), PP.getSelectorTable(), PP.getBuiltinInfo(), /*size_reserve*/0, /*DelayInit*/false); CI->setASTContext(Ctx); // Set up the ASTConsumers CI->setASTConsumer(new DeclCollector()); // Set up Sema CodeCompleteConsumer* CCC = 0; CI->createSema(TU_Complete, CCC); // Set CodeGen options // CI->getCodeGenOpts().DebugInfo = 1; // want debug info // CI->getCodeGenOpts().EmitDeclMetadata = 1; // For unloading, for later CI->getCodeGenOpts().OptimizationLevel = 0; // see pure SSA, that comes out CI->getCodeGenOpts().CXXCtorDtorAliases = 0; // aliasing the complete // ctor to the base ctor causes // the JIT to crash // When asserts are on, TURN ON not compare the VerifyModule assert(CI->getCodeGenOpts().VerifyModule = 1); return CI; }
int main() { using clang::CompilerInstance; using clang::TargetOptions; using clang::TargetInfo; using clang::FileEntry; using clang::Token; using clang::ASTContext; using clang::ASTConsumer; using clang::Parser; using clang::DiagnosticOptions; using clang::TextDiagnosticPrinter; CompilerInstance ci; DiagnosticOptions diagnosticOptions; ci.createDiagnostics(); std::shared_ptr<clang::TargetOptions> pto = std::make_shared<clang::TargetOptions>(); pto->Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto); ci.setTarget(pti); ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); ci.createPreprocessor(clang::TU_Complete); ci.getPreprocessorOpts().UsePredefines = false; ci.setASTConsumer(llvm::make_unique<ASTConsumer>()); ci.createASTContext(); ci.createSema(clang::TU_Complete, NULL); const FileEntry *pFile = ci.getFileManager().getFile("test.c"); ci.getSourceManager().setMainFileID( ci.getSourceManager().createFileID( pFile, clang::SourceLocation(), clang::SrcMgr::C_User)); clang::ParseAST(ci.getSema()); ci.getASTContext().Idents.PrintStats(); return 0; }
static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(CompilerInstance &CI) { using namespace clang::frontend; StringRef Action("unknown"); (void)Action; switch (CI.getFrontendOpts().ProgramAction) { case ASTDeclList: return llvm::make_unique<ASTDeclListAction>(); case ASTDump: return llvm::make_unique<ASTDumpAction>(); case ASTPrint: return llvm::make_unique<ASTPrintAction>(); case ASTView: return llvm::make_unique<ASTViewAction>(); case DumpRawTokens: return llvm::make_unique<DumpRawTokensAction>(); case DumpTokens: return llvm::make_unique<DumpTokensAction>(); case EmitAssembly: return llvm::make_unique<EmitAssemblyAction>(); case EmitBC: return llvm::make_unique<EmitBCAction>(); case EmitHTML: return llvm::make_unique<HTMLPrintAction>(); case EmitLLVM: return llvm::make_unique<EmitLLVMAction>(); case EmitLLVMOnly: return llvm::make_unique<EmitLLVMOnlyAction>(); case EmitCodeGenOnly: return llvm::make_unique<EmitCodeGenOnlyAction>(); case EmitObj: return llvm::make_unique<EmitObjAction>(); case FixIt: return llvm::make_unique<FixItAction>(); case GenerateModule: return llvm::make_unique<GenerateModuleFromModuleMapAction>(); case GenerateModuleInterface: return llvm::make_unique<GenerateModuleInterfaceAction>(); case GeneratePCH: return llvm::make_unique<GeneratePCHAction>(); case GeneratePTH: return llvm::make_unique<GeneratePTHAction>(); case InitOnly: return llvm::make_unique<InitOnlyAction>(); case ParseSyntaxOnly: return llvm::make_unique<SyntaxOnlyAction>(); case ModuleFileInfo: return llvm::make_unique<DumpModuleInfoAction>(); case VerifyPCH: return llvm::make_unique<VerifyPCHAction>(); case PluginAction: { for (FrontendPluginRegistry::iterator it = FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); it != ie; ++it) { if (it->getName() == CI.getFrontendOpts().ActionName) { std::unique_ptr<PluginASTAction> P(it->instantiate()); if ((P->getActionType() != PluginASTAction::ReplaceAction && P->getActionType() != PluginASTAction::Cmdline) || !P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs[it->getName()])) return nullptr; return std::move(P); } } CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << CI.getFrontendOpts().ActionName; return nullptr; } case PrintDeclContext: return llvm::make_unique<DeclContextPrintAction>(); case PrintPreamble: return llvm::make_unique<PrintPreambleAction>(); case PrintPreprocessedInput: { if (CI.getPreprocessorOutputOpts().RewriteIncludes) return llvm::make_unique<RewriteIncludesAction>(); return llvm::make_unique<PrintPreprocessedAction>(); } case RewriteMacros: return llvm::make_unique<RewriteMacrosAction>(); case RewriteTest: return llvm::make_unique<RewriteTestAction>(); #ifdef CLANG_ENABLE_OBJC_REWRITER case RewriteObjC: return llvm::make_unique<RewriteObjCAction>(); #else case RewriteObjC: Action = "RewriteObjC"; break; #endif #ifdef CLANG_ENABLE_ARCMT case MigrateSource: return llvm::make_unique<arcmt::MigrateSourceAction>(); #else case MigrateSource: Action = "MigrateSource"; break; #endif #ifdef CLANG_ENABLE_STATIC_ANALYZER case RunAnalysis: return llvm::make_unique<ento::AnalysisAction>(); #else case RunAnalysis: Action = "RunAnalysis"; break; #endif case RunPreprocessorOnly: return llvm::make_unique<PreprocessOnlyAction>(); } #if !defined(CLANG_ENABLE_ARCMT) || !defined(CLANG_ENABLE_STATIC_ANALYZER) \ || !defined(CLANG_ENABLE_OBJC_REWRITER) CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action; return 0; #else llvm_unreachable("Invalid program action!"); #endif }
int main() { using clang::CompilerInstance; using clang::TargetOptions; using clang::TargetInfo; using clang::FileEntry; using clang::Token; using clang::ASTContext; using clang::ASTConsumer; using clang::Parser; CompilerInstance ci; ci.createDiagnostics(0,NULL); TargetOptions to; to.Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), to); ci.setTarget(pti); ci.createFileManager(); ci.createSourceManager(ci.getFileManager()); ci.createPreprocessor(); ci.getPreprocessorOpts().UsePredefines = false; ASTConsumer *astConsumer = new ASTConsumer(); ci.setASTConsumer(astConsumer); ci.createASTContext(); ci.createSema(clang::TU_Complete, NULL); const FileEntry *pFile = ci.getFileManager().getFile("test.c"); ci.getSourceManager().createMainFileID(pFile); ci.getPreprocessor().EnterMainSourceFile(); ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(), &ci.getPreprocessor()); Parser parser(ci.getPreprocessor(), ci.getSema(), false /*skipFunctionBodies*/); parser.ParseTranslationUnit(); ci.getDiagnosticClient().EndSourceFile(); ci.getASTContext().Idents.PrintStats(); return 0; }
static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang, llvm::MemoryBuffer *UnresolvedInputFile, unsigned Offset, SwiftCodeCompletionConsumer &SwiftConsumer, ArrayRef<const char *> Args, std::string &Error) { trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; trace::initTraceInfo(SwiftArgs, UnresolvedInputFile->getBufferIdentifier(), Args); SwiftArgs.addFile(UnresolvedInputFile->getBufferIdentifier(), UnresolvedInputFile->getBuffer()); TracedOp.start(trace::OperationKind::CodeCompletionInit, SwiftArgs, { std::make_pair("Offset", std::to_string(Offset)), std::make_pair("InputBufferSize", std::to_string(UnresolvedInputFile->getBufferSize()))}); } // Resolve symlinks for the input file; we resolve them for the input files // in the arguments as well. // FIXME: We need the Swift equivalent of Clang's FileEntry. auto InputFile = llvm::MemoryBuffer::getMemBuffer( UnresolvedInputFile->getBuffer(), Lang.resolvePathSymlinks(UnresolvedInputFile->getBufferIdentifier())); CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; bool Failed = Lang.getASTManager().initCompilerInvocation( Invocation, Args, CI.getDiags(), InputFile->getBufferIdentifier(), Error); if (Failed) { return false; } if (Invocation.getInputFilenames().empty()) { Error = "no input filenames specified"; return false; } auto origBuffSize = InputFile->getBufferSize(); unsigned CodeCompletionOffset = Offset; if (CodeCompletionOffset > origBuffSize) { CodeCompletionOffset = origBuffSize; } const char *Position = InputFile->getBufferStart() + CodeCompletionOffset; std::unique_ptr<llvm::MemoryBuffer> NewBuffer = llvm::MemoryBuffer::getNewUninitMemBuffer(InputFile->getBufferSize() + 1, InputFile->getBufferIdentifier()); char *NewBuf = const_cast<char*>(NewBuffer->getBufferStart()); char *NewPos = std::copy(InputFile->getBufferStart(), Position, NewBuf); *NewPos = '\0'; std::copy(Position, InputFile->getBufferEnd(), NewPos+1); Invocation.setCodeCompletionPoint(NewBuffer.get(), CodeCompletionOffset); auto swiftCache = Lang.getCodeCompletionCache(); // Pin the cache. ide::CodeCompletionContext CompletionContext(swiftCache->getCache()); // Create a factory for code completion callbacks that will feed the // Consumer. std::unique_ptr<CodeCompletionCallbacksFactory> CompletionCallbacksFactory( ide::makeCodeCompletionCallbacksFactory(CompletionContext, SwiftConsumer)); Invocation.setCodeCompletionFactory(CompletionCallbacksFactory.get()); // FIXME: We need to be passing the buffers from the open documents. // It is not a huge problem in practice because Xcode auto-saves constantly. if (CI.setup(Invocation)) { // FIXME: error? return true; } TracedOp.finish(); if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; trace::initTraceInfo(SwiftArgs, InputFile->getBufferIdentifier(), Args); trace::initTraceFiles(SwiftArgs, CI); // Replace primary file with original content std::for_each(SwiftArgs.Files.begin(), SwiftArgs.Files.end(), [&] (trace::StringPairs::value_type &Pair) { if (Pair.first == InputFile->getBufferIdentifier()) { Pair.second = InputFile->getBuffer(); } }); TracedOp.start(trace::OperationKind::CodeCompletion, SwiftArgs, {std::make_pair("OriginalOffset", std::to_string(Offset)), std::make_pair("Offset", std::to_string(CodeCompletionOffset))}); } CloseClangModuleFiles scopedCloseFiles( *CI.getASTContext().getClangModuleLoader()); SwiftConsumer.setContext(&CI.getASTContext(), &Invocation, &CompletionContext); CI.performSema(); SwiftConsumer.clearContext(); return true; }
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override { TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); return llvm::make_unique<MyASTConsumer>(TheRewriter); }
int main(int argc, const char **argv, char * const *envp) { void *MainAddr = (void*) (intptr_t) GetExecutablePath; llvm::sys::Path Path = GetExecutablePath(argv[0]); TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); Diagnostic Diags(DiagID, DiagClient); Driver TheDriver(Path.str(), llvm::sys::getHostTriple(), "a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false, Diags); TheDriver.setTitle("clang interpreter"); // FIXME: This is a hack to try to force the driver to do something we can // recognize. We need to extend the driver library to support this use model // (basically, exactly one input, and the operation mode is hard wired). llvm::SmallVector<const char *, 16> Args(argv, argv + argc); Args.push_back("-fsyntax-only"); llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args)); if (!C) return 0; // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate. // We expect to get back exactly one command job, if we didn't something // failed. Extract that job from the compilation. const driver::JobList &Jobs = C->getJobs(); if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) { llvm::SmallString<256> Msg; llvm::raw_svector_ostream OS(Msg); C->PrintJob(OS, C->getJobs(), "; ", true); Diags.Report(diag::err_fe_expected_compiler_job) << OS.str(); return 1; } const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin()); if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { Diags.Report(diag::err_fe_expected_clang_command); return 1; } // Initialize a compiler invocation object from the clang (-cc1) arguments. const driver::ArgStringList &CCArgs = Cmd->getArguments(); llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation); CompilerInvocation::CreateFromArgs(*CI, const_cast<const char **>(CCArgs.data()), const_cast<const char **>(CCArgs.data()) + CCArgs.size(), Diags); // Show the invocation, with -v. if (CI->getHeaderSearchOpts().Verbose) { llvm::errs() << "clang invocation:\n"; C->PrintJob(llvm::errs(), C->getJobs(), "\n", true); llvm::errs() << "\n"; } // FIXME: This is copied from cc1_main.cpp; simplify and eliminate. // Create a compiler instance to handle the actual work. CompilerInstance Clang; Clang.setInvocation(CI.take()); // Create the compilers actual diagnostics engine. Clang.createDiagnostics(int(CCArgs.size()),const_cast<char**>(CCArgs.data())); if (!Clang.hasDiagnostics()) return 1; // Infer the builtin include path if unspecified. if (Clang.getHeaderSearchOpts().UseBuiltinIncludes && Clang.getHeaderSearchOpts().ResourceDir.empty()) Clang.getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(argv[0], MainAddr); // Create and execute the frontend to generate an LLVM bitcode module. llvm::OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction()); if (!Clang.ExecuteAction(*Act)) return 1; int Res = 255; if (llvm::Module *Module = Act->takeModule()) Res = Execute(Module, envp); // Shutdown. llvm::llvm_shutdown(); return Res; }