Skip to content

Commit e4e4f3e

Browse files
committed
Break Driver's dep on Frontend: make createCompilerInvocation uglier
But not even that much uglier; at all three call sites this will save an allocation, and for the most important one (SourceKit) we can now avoid creating a temporary CompilerInvocation just to copy into a longer-lived one. With this change, Driver no longer depends on Frontend, which means... well, slightly faster builds of the compiler itself, but not much else.
1 parent e224e31 commit e4e4f3e

File tree

6 files changed

+48
-44
lines changed

6 files changed

+48
-44
lines changed

include/swift/Driver/FrontendUtil.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,33 @@
1414
#define SWIFT_DRIVER_FRONTENDUTIL_H
1515

1616
#include "swift/Basic/LLVM.h"
17+
#include "llvm/ADT/STLExtras.h"
1718

1819
#include <memory>
1920

2021
namespace swift {
2122

22-
class CompilerInvocation;
2323
class DiagnosticEngine;
2424

2525
namespace driver {
2626

27-
/// \brief Creates a CompilerInvocation from the given driver arguments.
27+
/// Generates the list of arguments that would be passed to the compiler
28+
/// frontend from the given driver arguments.
2829
///
29-
/// \param ArgList The driver arguments for which a CompilerInvocation
30-
/// should be created.
31-
/// \param Diags The DiagnosticEngine which should be used for parsing arguments
30+
/// \param ArgList The driver arguments (i.e. normal arguments for \c swiftc).
31+
/// \param Diags The DiagnosticEngine used to report any errors parsing the
32+
/// arguments.
33+
/// \param Action Called with the list of frontend arguments if there were no
34+
/// errors in processing \p ArgList. This is a callback rather than a return
35+
/// value to avoid copying the arguments more than necessary.
3236
///
33-
/// \returns A fully-formed CompilerInvocation, or nullptr if one couldn't be
34-
/// created.
37+
/// \returns True on error, or if \p Action returns true.
3538
///
36-
/// \note This function is not intended to create CompilerInvocation instances
37-
/// which are suitable for use in REPL or immediate modes, since it will have
38-
/// the effect of overriding the frontend's requested action to
39-
/// FrontendOptions::ActionType::Parse.
40-
std::unique_ptr<CompilerInvocation> createCompilerInvocation(
41-
ArrayRef<const char *> ArgList, DiagnosticEngine &Diags);
39+
/// \note This function is not intended to create invocations which are
40+
/// suitable for use in REPL or immediate modes.
41+
bool getSingleFrontendInvocationFromDriverArguments(
42+
ArrayRef<const char *> ArgList, DiagnosticEngine &Diags,
43+
llvm::function_ref<bool(ArrayRef<const char *> FrontendArgs)> Action);
4244

4345
} // end namespace driver
4446
} // end namespace swift

lib/Driver/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ set(swiftDriver_targetDefines)
1919
add_swift_library(swiftDriver STATIC
2020
${swiftDriver_sources}
2121
DEPENDS SwiftOptions
22-
LINK_LIBRARIES swiftAST swiftBasic swiftFrontend swiftOption)
22+
LINK_LIBRARIES swiftAST swiftBasic swiftOption)
2323

2424
# Generate the static-stdlib-args.lnk file used by -static-stdlib option
2525
# for 'GenericUnix' (eg linux)

lib/Driver/FrontendUtil.cpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
#include "swift/Driver/Driver.h"
1919
#include "swift/Driver/Job.h"
2020
#include "swift/Driver/ToolChain.h"
21-
#include "swift/Frontend/Frontend.h"
21+
#include "llvm/Option/ArgList.h"
2222

2323
using namespace swift;
2424
using namespace swift::driver;
2525

26-
std::unique_ptr<CompilerInvocation>
27-
swift::driver::createCompilerInvocation(ArrayRef<const char *> Argv,
28-
DiagnosticEngine &Diags) {
26+
bool swift::driver::getSingleFrontendInvocationFromDriverArguments(
27+
ArrayRef<const char *> Argv, DiagnosticEngine &Diags,
28+
llvm::function_ref<bool(ArrayRef<const char *> FrontendArgs)> Action) {
2929
SmallVector<const char *, 16> Args;
3030
Args.push_back("<swiftc>"); // FIXME: Remove dummy argument.
3131
Args.insert(Args.end(), Argv.begin(), Argv.end());
@@ -55,16 +55,16 @@ swift::driver::createCompilerInvocation(ArrayRef<const char *> Argv,
5555
std::unique_ptr<llvm::opt::InputArgList> ArgList =
5656
TheDriver.parseArgStrings(ArrayRef<const char *>(Args).slice(1));
5757
if (Diags.hadAnyError())
58-
return nullptr;
58+
return true;
5959

6060
std::unique_ptr<ToolChain> TC = TheDriver.buildToolChain(*ArgList);
6161
if (Diags.hadAnyError())
62-
return nullptr;
62+
return true;
6363

6464
std::unique_ptr<Compilation> C =
6565
TheDriver.buildCompilation(*TC, std::move(ArgList));
6666
if (!C || C->getJobs().empty())
67-
return nullptr; // Don't emit an error; one should already have been emitted
67+
return true; // Don't emit an error; one should already have been emitted
6868

6969
SmallPtrSet<const Job *, 4> CompileCommands;
7070
for (const Job *Cmd : C->getJobs())
@@ -74,22 +74,15 @@ swift::driver::createCompilerInvocation(ArrayRef<const char *> Argv,
7474
if (CompileCommands.size() != 1) {
7575
// TODO: include Jobs in the diagnostic.
7676
Diags.diagnose(SourceLoc(), diag::error_expected_one_frontend_job);
77-
return nullptr;
77+
return true;
7878
}
7979

8080
const Job *Cmd = *CompileCommands.begin();
8181
if (StringRef("-frontend") != Cmd->getArguments().front()) {
8282
Diags.diagnose(SourceLoc(), diag::error_expected_frontend_command);
83-
return nullptr;
83+
return true;
8484
}
8585

86-
std::unique_ptr<CompilerInvocation> Invocation(new CompilerInvocation());
8786
const llvm::opt::ArgStringList &BaseFrontendArgs = Cmd->getArguments();
88-
ArrayRef<const char *> FrontendArgs =
89-
llvm::makeArrayRef(BaseFrontendArgs.data() + 1,
90-
BaseFrontendArgs.data() + BaseFrontendArgs.size());
91-
if (Invocation->parseArgs(FrontendArgs, Diags))
92-
return nullptr; // Don't emit an error; one should already have been emitted
93-
94-
return Invocation;
87+
return Action(llvm::makeArrayRef(BaseFrontendArgs).drop_front());
9588
}

tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,12 @@ bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
434434
Args.push_back("-resource-dir");
435435
Args.push_back(Impl.RuntimeResourcePath.c_str());
436436

437-
if (auto driverInvocation = driver::createCompilerInvocation(Args, Diags)) {
438-
Invocation = *driverInvocation;
439-
} else {
437+
bool HadError = driver::getSingleFrontendInvocationFromDriverArguments(
438+
Args, Diags, [&](ArrayRef<const char *> FrontendArgs) {
439+
return Invocation.parseArgs(FrontendArgs, Diags);
440+
});
441+
442+
if (HadError) {
440443
// FIXME: Get the actual diagnostic.
441444
Error = "error when parsing the compiler arguments";
442445
return true;

tools/swift-ide-test/ModuleAPIDiff.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -907,27 +907,30 @@ int swift::doGenerateModuleAPIDescription(StringRef MainExecutablePath,
907907
DiagnosticEngine Diags(SM);
908908
Diags.addConsumer(PDC);
909909

910-
std::unique_ptr<CompilerInvocation> Invocation =
911-
driver::createCompilerInvocation(CStringArgs, Diags);
910+
CompilerInvocation Invocation;
911+
bool HadError = driver::getSingleFrontendInvocationFromDriverArguments(
912+
CStringArgs, Diags, [&](ArrayRef<const char *> FrontendArgs) {
913+
return Invocation.parseArgs(FrontendArgs, Diags);
914+
});
912915

913-
if (!Invocation) {
916+
if (HadError) {
914917
llvm::errs() << "error: unable to create a CompilerInvocation\n";
915918
return 1;
916919
}
917920

918-
Invocation->setMainExecutablePath(MainExecutablePath);
921+
Invocation.setMainExecutablePath(MainExecutablePath);
919922

920923
CompilerInstance CI;
921924
CI.addDiagnosticConsumer(&PDC);
922-
if (CI.setup(*Invocation))
925+
if (CI.setup(Invocation))
923926
return 1;
924927
CI.performSema();
925928

926929
PrintOptions Options = PrintOptions::printEverything();
927930

928931
ModuleDecl *M = CI.getMainModule();
929-
M->getMainSourceFile(Invocation->getSourceFileKind()).print(llvm::outs(),
930-
Options);
932+
M->getMainSourceFile(Invocation.getSourceFileKind()).print(llvm::outs(),
933+
Options);
931934

932935
auto SMAModel = createSMAModel(M);
933936
llvm::yaml::Output YOut(llvm::outs());

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,10 +2909,13 @@ static int doTestCreateCompilerInvocation(ArrayRef<const char *> Args) {
29092909
DiagnosticEngine Diags(SM);
29102910
Diags.addConsumer(PDC);
29112911

2912-
std::unique_ptr<CompilerInvocation> CI =
2913-
driver::createCompilerInvocation(Args, Diags);
2912+
CompilerInvocation CI;
2913+
bool HadError = driver::getSingleFrontendInvocationFromDriverArguments(
2914+
Args, Diags, [&](ArrayRef<const char *> FrontendArgs) {
2915+
return CI.parseArgs(FrontendArgs, Diags);
2916+
});
29142917

2915-
if (!CI) {
2918+
if (HadError) {
29162919
llvm::errs() << "error: unable to create a CompilerInvocation\n";
29172920
return 1;
29182921
}

0 commit comments

Comments
 (0)