From dc081384d5ecaf41806063fd17cc79d99a1ec391 Mon Sep 17 00:00:00 2001 From: ykiko Date: Sat, 7 Dec 2024 21:54:00 +0800 Subject: [PATCH] Some clarification for `CompliationParams`. --- include/Compiler/Compiler.h | 43 ++++++++++++++++++----- src/Compiler/Compiler.cpp | 52 +++++++++++----------------- src/Feature/CodeCompletion.cpp | 2 +- src/Server/Scheduler.cpp | 18 +++++----- unittests/Compiler/Compiler.cpp | 14 ++++---- unittests/Compiler/Resolver.cpp | 2 +- unittests/Feature/CodeCompletion.cpp | 2 +- unittests/Index/Tester.h | 2 +- unittests/Test.h | 4 +-- 9 files changed, 78 insertions(+), 61 deletions(-) diff --git a/include/Compiler/Compiler.h b/include/Compiler/Compiler.h index 54e28593..b6bec12d 100644 --- a/include/Compiler/Compiler.h +++ b/include/Compiler/Compiler.h @@ -95,10 +95,13 @@ private: struct PCHInfo { /// PCM file path. std::string path; + /// Source file path. - std::string mainpath; + std::string srcPath; + /// The content of source file used to build this PCM. std::string preamble; + /// Files involved in building this PCM. std::vector deps; @@ -115,6 +118,10 @@ struct PCHInfo { struct PCMInfo { /// PCM file path. std::string path; + + /// Source file path. + std::string srcPath; + /// Module name. std::string name; @@ -122,26 +129,43 @@ struct PCMInfo { }; struct CompliationParams { + /// Source file path. + llvm::SmallString<128> srcPath; + + /// Source file content. llvm::StringRef content; - llvm::SmallString<128> path; - llvm::SmallString<128> outpath; - llvm::SmallString<128> mainpath; + + /// - If we are building PCH, we need a size to verify the bounds of preamble. That is + /// which source code range the PCH will cover. + /// - If we are building main file AST for header, we need a size to cut off code after the + /// `#include` directive that includes the header to speed up the parsing. + std::optional bounds; + + /// Output file path. + llvm::SmallString<128> outPath; + + /// Command line arguments. llvm::ArrayRef args; + llvm::IntrusiveRefCntPtr vfs = new ThreadSafeFS(); + /// Information about reuse PCH. std::string pch; - clang::PreambleBounds bounds = {0, false}; + clang::PreambleBounds pchBounds = {0, false}; /// Information about reuse PCM(name, path). llvm::SmallVector> pcms; - llvm::IntrusiveRefCntPtr vfs = new ThreadSafeFS(); + /// Code completion file:line:column. + llvm::StringRef file = ""; + uint32_t line = 0; + uint32_t column = 0; - uint32_t line = 0, column = 0; + void computeBounds(); void addPCH(const PCHInfo& info) { pch = info.path; - bounds = info.bounds(); + pchBounds = info.bounds(); } void addPCM(const PCMInfo& info) { @@ -154,10 +178,13 @@ struct CompliationParams { /// their reusability and update in time. llvm::Expected compile(CompliationParams& params); +/// Build PCH from given file path and content. llvm::Expected compile(CompliationParams& params, PCHInfo& out); +/// Build PCM from given file path and content. llvm::Expected compile(CompliationParams& params, PCMInfo& out); +/// Run code completion at the given location. llvm::Expected compile(CompliationParams& params, clang::CodeCompleteConsumer* consumer); } // namespace clice diff --git a/src/Compiler/Compiler.cpp b/src/Compiler/Compiler.cpp index 9676af63..b33bcef7 100644 --- a/src/Compiler/Compiler.cpp +++ b/src/Compiler/Compiler.cpp @@ -46,13 +46,20 @@ auto createInstance(CompliationParams& params) { adjustInvocation(instance->getInvocation()); + /// FIXME: figure out whether we need to retain remapped file buffers. + /// Add remapped files, if bounds is provided, cut off the content. + std::size_t size = + params.bounds.has_value() ? params.bounds.value().Size : params.content.size(); + auto buffer = llvm::MemoryBuffer::getMemBufferCopy(params.content.substr(0, size)); + instance->getPreprocessorOpts().addRemappedFile(params.srcPath, buffer.release()); + return instance; } void applyPreamble(clang::CompilerInstance& instance, CompliationParams& params) { auto& PPOpts = instance.getPreprocessorOpts(); auto& pch = params.pch; - auto& bounds = params.bounds; + auto& bounds = params.pchBounds; auto& pcms = params.pcms; if(bounds.Size != 0) { PPOpts.UsePredefines = false; @@ -128,46 +135,35 @@ llvm::Expected ExecuteAction(std::unique_ptr i llvm::Expected compile(CompliationParams& params) { auto instance = createInstance(params); - auto buffer = llvm::MemoryBuffer::getMemBufferCopy(params.content); - instance->getPreprocessorOpts().addRemappedFile(params.path, buffer.release()); - applyPreamble(*instance, params); return ExecuteAction(std::move(instance), clang::frontend::ActionKind::ParseSyntaxOnly); } llvm::Expected compile(CompliationParams& params, PCHInfo& out) { + assert(params.bounds.has_value() && "Preamble bounds is required to build PCH"); + auto instance = createInstance(params); - clang::PreambleBounds bounds = {0, false}; - if(params.mainpath.empty() || params.mainpath == params.path) { - /// If mainpath is equal to path, just tokenize the content to get preamble bounds. - bounds = clang::Lexer::ComputePreamble(params.content, {}, false); - } else { - /// FIXME: if the mainpath is not equal to path, we need to preprocess the mainpath to get - /// the preamble bounds. - std::terminate(); - } - /// Set options to generate PCH. - instance->getFrontendOpts().OutputFile = params.outpath.str(); + instance->getFrontendOpts().OutputFile = params.outPath.str(); instance->getFrontendOpts().ProgramAction = clang::frontend::GeneratePCH; instance->getPreprocessorOpts().PrecompiledPreambleBytes = {0, false}; instance->getPreprocessorOpts().GeneratePreamble = true; instance->getLangOpts().CompilingPCH = true; - auto buffer = llvm::MemoryBuffer::getMemBufferCopy(params.content.substr(0, bounds.Size)); - instance->getPreprocessorOpts().addRemappedFile(params.path, buffer.release()); - if(auto info = ExecuteAction(std::move(instance), clang::frontend::ActionKind::GeneratePCH)) { - out.path = params.outpath.str(); - out.mainpath = params.mainpath.str(); - out.preamble = params.content.substr(0, bounds.Size).str(); + out.path = params.outPath.str(); + out.srcPath = params.srcPath.str(); + + auto& bounds = *params.bounds; out.preamble = params.content.substr(0, bounds.Size).str(); if(bounds.PreambleEndsAtStartOfLine) { out.preamble.append("@"); } + /// TODO: collect files involved in building this PCH. + return std::move(*info); } else { return info.takeError(); @@ -178,18 +174,16 @@ llvm::Expected compile(CompliationParams& params, PCMInfo& out) { auto instance = createInstance(params); /// Set options to generate PCM. - instance->getFrontendOpts().OutputFile = params.outpath.str(); + instance->getFrontendOpts().OutputFile = params.outPath.str(); instance->getFrontendOpts().ProgramAction = clang::frontend::GenerateReducedModuleInterface; - auto buffer = llvm::MemoryBuffer::getMemBufferCopy(params.content); - instance->getPreprocessorOpts().addRemappedFile(params.path, buffer.release()); - applyPreamble(*instance, params); if(auto info = ExecuteAction(std::move(instance), clang::frontend::ActionKind::GenerateReducedModuleInterface)) { - out.path = params.outpath.str(); + out.path = params.outPath.str(); out.name = info->context().getCurrentNamedModule()->Name; + return std::move(*info); } else { return info.takeError(); @@ -200,15 +194,11 @@ llvm::Expected compile(CompliationParams& params, clang::CodeCompleteCo auto instance = createInstance(params); /// Set options to run code completion. - instance->getFrontendOpts().CodeCompletionAt.FileName = params.path.str(); + instance->getFrontendOpts().CodeCompletionAt.FileName = params.srcPath.str(); instance->getFrontendOpts().CodeCompletionAt.Line = params.line; instance->getFrontendOpts().CodeCompletionAt.Column = params.column; instance->setCodeCompletionConsumer(consumer); - auto buffer = llvm::MemoryBuffer::getMemBufferCopy(params.content); - /// FIXME: Check PPOpts.RetainRemappedFileBuffers. - instance->getPreprocessorOpts().addRemappedFile(params.path, buffer.release()); - applyPreamble(*instance, params); return ExecuteAction(std::move(instance), clang::frontend::ActionKind::ParseSyntaxOnly); diff --git a/src/Feature/CodeCompletion.cpp b/src/Feature/CodeCompletion.cpp index b2440f4b..34540423 100644 --- a/src/Feature/CodeCompletion.cpp +++ b/src/Feature/CodeCompletion.cpp @@ -208,7 +208,7 @@ proto::CompletionResult codeCompletion(CompliationParams& params, proto::CompletionResult completions; auto consumer = new CodeCompletionCollector(completions, line, column, params.content); - params.path = file; + params.srcPath = file; params.line = line; params.column = column; diff --git a/src/Server/Scheduler.cpp b/src/Server/Scheduler.cpp index 6982cd3f..0fd60658 100644 --- a/src/Server/Scheduler.cpp +++ b/src/Server/Scheduler.cpp @@ -12,21 +12,21 @@ async::promise Scheduler::updatePCH(llvm::StringRef filepath, Tracer tracer; CompliationParams params; - params.path = filepath; + params.srcPath = filepath; params.content = content; params.args = args; - params.outpath = filepath; - path::replace_path_prefix(params.outpath, + params.outPath = filepath; + path::replace_path_prefix(params.outPath, config::workplace(), config::frontend().cache_directory); - path::replace_extension(params.outpath, ".pch"); + path::replace_extension(params.outPath, ".pch"); - log::info("Start building PCH for {0} at {1}", params.path, params.outpath); + log::info("Start building PCH for {0} at {1}", params.srcPath, params.outPath); PCHInfo pch; co_await async::schedule_task([&] { - auto dir = path::parent_path(params.outpath); + auto dir = path::parent_path(params.outPath); if(!fs::exists(dir)) { if(auto error = fs::create_directories(dir)) { log::fatal("Failed to create directory {0}, because {1}, build PCH stopped", @@ -98,7 +98,7 @@ async::promise Scheduler::buildAST(llvm::StringRef filepath, llvm::StringR log::info("Start building AST for {0}, command: [{1}]", filepath, command.str()); CompliationParams params; - params.path = path; + params.srcPath = path; params.content = content; params.args = args; params.addPCH(pchs.at(filepath)); @@ -162,13 +162,13 @@ async::promise Scheduler::codeComplete(llvm::StringRef }; CompliationParams params; - params.path = path; + params.srcPath = path; params.args = args; params.content = iter->second.content; /// through arguments to judge is it a module. bool isModule = false; - co_await (isModule ? updatePCM() : updatePCH(params.path, params.content, args)); + co_await (isModule ? updatePCM() : updatePCH(params.srcPath, params.content, args)); params.addPCH(pchs.at(filepath)); Tracer tracer; diff --git a/unittests/Compiler/Compiler.cpp b/unittests/Compiler/Compiler.cpp index 519d0c70..6bea7b99 100644 --- a/unittests/Compiler/Compiler.cpp +++ b/unittests/Compiler/Compiler.cpp @@ -25,7 +25,7 @@ int main(){ }; CompliationParams params; - params.path = "main.cpp"; + params.srcPath = "main.cpp"; params.content = code; params.args = compileArgs; @@ -63,9 +63,9 @@ int main(){ } CompliationParams params; - params.path = "main.cpp"; + params.srcPath = "main.cpp"; params.content = code; - params.outpath = outpath; + params.outPath = outpath; params.args = compileArgs; PCHInfo pch; @@ -104,9 +104,9 @@ export int foo() { }; CompliationParams params; - params.path = "main.cppm"; + params.srcPath = "main.cppm"; params.content = code; - params.outpath = outpath; + params.outPath = outpath; params.args = compileArgs; PCMInfo pcm; @@ -128,7 +128,7 @@ int main(){ "main.cpp", }; - params.path = "main.cpp"; + params.srcPath = "main.cpp"; params.content = code2; params.args = compileArgs; params.addPCM(pcm); @@ -150,7 +150,7 @@ export int foo = 1; }; CompliationParams params; - params.path = "main.cppm"; + params.srcPath = "main.cppm"; params.content = code; params.args = compileArgs; params.line = 3; diff --git a/unittests/Compiler/Resolver.cpp b/unittests/Compiler/Resolver.cpp index 060ac68d..cee95c1f 100644 --- a/unittests/Compiler/Resolver.cpp +++ b/unittests/Compiler/Resolver.cpp @@ -18,7 +18,7 @@ struct TemplateResolverTester : public clang::RecursiveASTVisitor(); } @@ -158,7 +158,7 @@ public: llvm::SmallVector args = { "clang++", standard, - params.path.c_str(), + params.srcPath.c_str(), "-resource-dir", test::resource_dir().data(), };