From 11089669593e64ee6300be0d3b26204fb3c3957d Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 3 Dec 2009 01:54:28 +0000 Subject: [PATCH] Switch clang_createTranslationUnitFromSourceFile to use ASTUnit::LoadFromCommandLine. - This is much faster, as it avoids the overhead of dumping an AST file to disk and reloading it. - For debugging purposes, there is a clang_setUseExternalASTGeneration hook which can be used to disable this. On the Sketch Cocoa app, the speedup is pretty nice, especially when using a PCH file while scanning the source: Wall time to c-index-test all files (no PCH): Old: 23.4221 New: 12.3884 Wall time to c-index-test all files (with a PCH, and "local" mode): Old: 10.9233 New: 1.9038 llvm-svn: 90385 --- clang/include/clang-c/Index.h | 56 +++++++++++++++++-------- clang/tools/CIndex/CIndex.cpp | 43 ++++++++++++++++++- clang/tools/CIndex/CIndex.exports | 3 +- clang/tools/c-index-test/c-index-test.c | 5 +++ 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 8e6eeb5422de..4e768097c402 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -202,8 +202,22 @@ CINDEX_LINKAGE void clang_disposeString(CXString string); */ CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, int displayDiagnostics); -CINDEX_LINKAGE void clang_disposeIndex(CXIndex); -CINDEX_LINKAGE CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); +CINDEX_LINKAGE void clang_disposeIndex(CXIndex index); +CINDEX_LINKAGE CXString +clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); + +/* + * \brief Request that AST's be generated external for API calls which parse + * source code on the fly, e.g. \see createTranslationUnitFromSourceFile. + * + * Note: This is for debugging purposes only, and may be removed at a later + * date. + * + * \param index - The index to update. + * \param value - The new flag value. + */ +CINDEX_LINKAGE void clang_setUseExternalASTGeneration(CXIndex index, + int value); /* * \brief Create a translation unit from an AST file (-emit-ast). @@ -211,6 +225,7 @@ CINDEX_LINKAGE CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUni CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit( CXIndex, const char *ast_filename ); + /** * \brief Destroy the specified CXTranslationUnit object. */ @@ -220,20 +235,25 @@ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); * \brief Return the CXTranslationUnit for a given source file and the provided * command line arguments one would pass to the compiler. * - * Note: The 'source_filename' argument is optional. If the caller provides a NULL pointer, - * the name of the source file is expected to reside in the specified command line arguments. + * Note: The 'source_filename' argument is optional. If the caller provides a + * NULL pointer, the name of the source file is expected to reside in the + * specified command line arguments. * - * Note: When encountered in 'clang_command_line_args', the following options are ignored: + * Note: When encountered in 'clang_command_line_args', the following options + * are ignored: * * '-c' * '-emit-ast' * '-fsyntax-only' * '-o ' (both '-o' and '' are ignored) * + * + * \param source_filename - The name of the source file to load, or NULL if the + * source file is included in clang_command_line_args. */ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( - CXIndex CIdx, - const char *source_filename /* specify NULL if the source file is in clang_command_line_args */, + CXIndex CIdx, + const char *source_filename, int num_clang_command_line_args, const char **clang_command_line_args ); @@ -253,13 +273,14 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( } static void usage { clang_loadTranslationUnit(CXTranslationUnit, printObjCInterfaceNames); - } + } */ typedef void *CXClientData; typedef void (*CXTranslationUnitIterator)(CXTranslationUnit, CXCursor, CXClientData); -CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator, - CXClientData); +CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit, + CXTranslationUnitIterator, + CXClientData); /* Usage: clang_loadDeclaration(). Will load the declaration, issuing a @@ -320,8 +341,9 @@ CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl); Usage: clang_getCursor() will translate a source/line/column position into an AST cursor (to derive semantic information from the source code). */ -CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name, - unsigned line, unsigned column); +CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, + const char *source_name, + unsigned line, unsigned column); CINDEX_LINKAGE CXCursor clang_getNullCursor(void); @@ -634,11 +656,11 @@ clang_getNumCompletionChunks(CXCompletionString completion_string); * \param CIdx the \c CXIndex instance that will be used to perform code * completion. * - * \param source_filename the name of the source file that should be parsed - * to perform code-completion. This source file must be the same as or - * include the filename described by \p complete_filename, or no code-completion - * results will be produced. NOTE: One can also specify NULL for this argument if - * the source file is included in command_line_args. + * \param source_filename the name of the source file that should be parsed to + * perform code-completion. This source file must be the same as or include the + * filename described by \p complete_filename, or no code-completion results + * will be produced. NOTE: One can also specify NULL for this argument if the + * source file is included in command_line_args. * * \param num_command_line_args the number of command-line arguments stored in * \p command_line_args. diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index a5b7e996229a..8ef9fb5ca090 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -324,6 +324,11 @@ public: DisplayDiagnostics = Display; } + bool getUseExternalASTGeneration() const { return UseExternalASTGeneration; } + void setUseExternalASTGeneration(bool Value) { + UseExternalASTGeneration = Value; + } + Diagnostic &getDiags() { return DisplayDiagnostics ? *TextDiags : IgnoreDiags; } @@ -466,6 +471,12 @@ void clang_disposeIndex(CXIndex CIdx) { delete static_cast(CIdx); } +void clang_setUseExternalASTGeneration(CXIndex CIdx, int value) { + assert(CIdx && "Passed null CXIndex"); + CIndexer *CXXIdx = static_cast(CIdx); + CXXIdx->setUseExternalASTGeneration(value); +} + // FIXME: need to pass back error info. CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, const char *ast_filename) { @@ -485,6 +496,24 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, assert(CIdx && "Passed null CXIndex"); CIndexer *CXXIdx = static_cast(CIdx); + if (!CXXIdx->getUseExternalASTGeneration()) { + llvm::SmallVector Args; + + // The 'source_filename' argument is optional. If the caller does not + // specify it then it is assumed that the source file is specified + // in the actual argument list. + if (source_filename) + Args.push_back(source_filename); + Args.insert(Args.end(), command_line_args, + command_line_args + num_command_line_args); + + void *MainAddr = (void *)(uintptr_t)clang_createTranslationUnit; + return ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(), + CXXIdx->getDiags(), "", MainAddr, + CXXIdx->getOnlyLocalDecls(), + /* UseBumpAllocator = */ true); + } + // Build up the arguments for invoking 'clang'. std::vector argv; @@ -572,8 +601,18 @@ void clang_loadTranslationUnit(CXTranslationUnit CTUnit, ASTUnit *CXXUnit = static_cast(CTUnit); ASTContext &Ctx = CXXUnit->getASTContext(); - TUVisitor DVisit(CTUnit, callback, CData, - CXXUnit->getOnlyLocalDecls()? 1 : Decl::MaxPCHLevel); + unsigned PCHLevel = Decl::MaxPCHLevel; + + // Set the PCHLevel to filter out unwanted decls if requested. + if (CXXUnit->getOnlyLocalDecls()) { + PCHLevel = 0; + + // If the main input was an AST, bump the level. + if (CXXUnit->isMainFileAST()) + ++PCHLevel; + } + + TUVisitor DVisit(CTUnit, callback, CData, PCHLevel); DVisit.Visit(Ctx.getTranslationUnitDecl()); } diff --git a/clang/tools/CIndex/CIndex.exports b/clang/tools/CIndex/CIndex.exports index 2892ce50e70d..458ad1028359 100644 --- a/clang/tools/CIndex/CIndex.exports +++ b/clang/tools/CIndex/CIndex.exports @@ -6,6 +6,7 @@ _clang_disposeIndex _clang_disposeString _clang_disposeTranslationUnit _clang_equalCursors +_clang_getCString _clang_getCompletionChunkCompletionString _clang_getCompletionChunkKind _clang_getCompletionChunkText @@ -19,7 +20,6 @@ _clang_getCursorLine _clang_getCursorSource _clang_getCursorSourceFile _clang_getCursorSpelling -_clang_getCString _clang_getDeclColumn _clang_getDeclLine _clang_getDeclSource @@ -41,3 +41,4 @@ _clang_isInvalid _clang_isReference _clang_loadDeclaration _clang_loadTranslationUnit +_clang_setUseExternalASTGeneration diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index efff1ae3188c..7300585a1d88 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -179,12 +179,17 @@ int perform_test_load_tu(const char *file, const char *filter) { } int perform_test_load_source(int argc, const char **argv, const char *filter) { + const char *UseExternalASTs = + getenv("CINDEXTEST_USE_EXTERNAL_AST_GENERATION"); CXIndex Idx; CXTranslationUnit TU; Idx = clang_createIndex(/* excludeDeclsFromPCH */ !strcmp(filter, "local") ? 1 : 0, /* displayDiagnostics */ 1); + if (UseExternalASTs && strlen(UseExternalASTs)) + clang_setUseExternalASTGeneration(Idx, 1); + TU = clang_createTranslationUnitFromSourceFile(Idx, 0, argc, argv); if (!TU) { fprintf(stderr, "Unable to load translation unit!\n");