Skip to content

Commit 4339275

Browse files
committed
[Driver] Use shared singleton instance of DriverOptTable
Summary: This significantly reduces the time required to run clangd tests, by ~10%. Should also have an effect on other tests that run command-line parsing multiple times inside a single invocation. Reviewers: gribozavr, sammccall Reviewed By: sammccall Subscribers: kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67163 llvm-svn: 370908
1 parent cbf1f3b commit 4339275

File tree

12 files changed

+87
-83
lines changed

12 files changed

+87
-83
lines changed

clang-tools-extra/modularize/Modularize.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,13 @@ std::string CommandLine;
337337

338338
// Helper function for finding the input file in an arguments list.
339339
static std::string findInputFile(const CommandLineArguments &CLArgs) {
340-
std::unique_ptr<OptTable> Opts(createDriverOptTable());
341340
const unsigned IncludedFlagsBitmask = options::CC1Option;
342341
unsigned MissingArgIndex, MissingArgCount;
343342
SmallVector<const char *, 256> Argv;
344343
for (auto I = CLArgs.begin(), E = CLArgs.end(); I != E; ++I)
345344
Argv.push_back(I->c_str());
346-
InputArgList Args = Opts->ParseArgs(Argv, MissingArgIndex, MissingArgCount,
347-
IncludedFlagsBitmask);
345+
InputArgList Args = getDriverOptTable().ParseArgs(
346+
Argv, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask);
348347
std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
349348
return ModularizeUtilities::getCanonicalPath(Inputs.back());
350349
}

clang/include/clang/Driver/Driver.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "clang/Basic/Diagnostic.h"
1313
#include "clang/Basic/LLVM.h"
1414
#include "clang/Driver/Action.h"
15+
#include "clang/Driver/Options.h"
1516
#include "clang/Driver/Phases.h"
1617
#include "clang/Driver/ToolChain.h"
1718
#include "clang/Driver/Types.h"
@@ -56,8 +57,6 @@ enum LTOKind {
5657
/// Driver - Encapsulate logic for constructing compilation processes
5758
/// from a set of gcc-driver-like command line arguments.
5859
class Driver {
59-
std::unique_ptr<llvm::opt::OptTable> Opts;
60-
6160
DiagnosticsEngine &Diags;
6261

6362
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
@@ -301,7 +300,7 @@ class Driver {
301300

302301
const std::string &getConfigFile() const { return ConfigFile; }
303302

304-
const llvm::opt::OptTable &getOpts() const { return *Opts; }
303+
const llvm::opt::OptTable &getOpts() const { return getDriverOptTable(); }
305304

306305
const DiagnosticsEngine &getDiags() const { return Diags; }
307306

clang/include/clang/Driver/Options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ enum ID {
4747
};
4848
}
4949

50-
std::unique_ptr<llvm::opt::OptTable> createDriverOptTable();
50+
const llvm::opt::OptTable &getDriverOptTable();
5151
}
5252
}
5353

clang/lib/Driver/Driver.cpp

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,16 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath,
120120
Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
121121
DiagnosticsEngine &Diags,
122122
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
123-
: Opts(createDriverOptTable()), Diags(Diags), VFS(std::move(VFS)),
124-
Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
125-
LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
126-
SysRoot(DEFAULT_SYSROOT), DriverTitle("clang LLVM compiler"),
127-
CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
128-
CCLogDiagnosticsFilename(nullptr), CCCPrintBindings(false),
129-
CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
130-
CCGenDiagnostics(false), TargetTriple(TargetTriple),
131-
CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
132-
GenReproducer(false), SuppressMissingInputWarning(false) {
123+
: Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
124+
SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
125+
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
126+
DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr),
127+
CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
128+
CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false),
129+
CCLogDiagnostics(false), CCGenDiagnostics(false),
130+
TargetTriple(TargetTriple), CCCGenericGCCName(""), Saver(Alloc),
131+
CheckInputsExist(true), GenReproducer(false),
132+
SuppressMissingInputWarning(false) {
133133

134134
// Provide a sane fallback if no VFS is specified.
135135
if (!this->VFS)
@@ -310,7 +310,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
310310
return FinalPhase;
311311
}
312312

313-
static Arg *MakeInputArg(DerivedArgList &Args, OptTable &Opts,
313+
static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts,
314314
StringRef Value, bool Claim = true) {
315315
Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value,
316316
Args.getBaseArgs().MakeIndex(Value), Value.data());
@@ -321,6 +321,7 @@ static Arg *MakeInputArg(DerivedArgList &Args, OptTable &Opts,
321321
}
322322

323323
DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
324+
const llvm::opt::OptTable &Opts = getOpts();
324325
DerivedArgList *DAL = new DerivedArgList(Args);
325326

326327
bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
@@ -337,12 +338,12 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
337338
A->getOption().matches(options::OPT_Xlinker)) &&
338339
A->containsValue("--no-demangle")) {
339340
// Add the rewritten no-demangle argument.
340-
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_Xlinker__no_demangle));
341+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_Xlinker__no_demangle));
341342

342343
// Add the remaining values as Xlinker arguments.
343344
for (StringRef Val : A->getValues())
344345
if (Val != "--no-demangle")
345-
DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker), Val);
346+
DAL->AddSeparateArg(A, Opts.getOption(options::OPT_Xlinker), Val);
346347

347348
continue;
348349
}
@@ -355,12 +356,11 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
355356
A->getValue(0) == StringRef("-MMD"))) {
356357
// Rewrite to -MD/-MMD along with -MF.
357358
if (A->getValue(0) == StringRef("-MD"))
358-
DAL->AddFlagArg(A, Opts->getOption(options::OPT_MD));
359+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_MD));
359360
else
360-
DAL->AddFlagArg(A, Opts->getOption(options::OPT_MMD));
361+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_MMD));
361362
if (A->getNumValues() == 2)
362-
DAL->AddSeparateArg(A, Opts->getOption(options::OPT_MF),
363-
A->getValue(1));
363+
DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue(1));
364364
continue;
365365
}
366366

@@ -371,13 +371,13 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
371371
// Rewrite unless -nostdlib is present.
372372
if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx &&
373373
Value == "stdc++") {
374-
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_stdcxx));
374+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_stdcxx));
375375
continue;
376376
}
377377

378378
// Rewrite unconditionally.
379379
if (Value == "cc_kext") {
380-
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_cckext));
380+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_cckext));
381381
continue;
382382
}
383383
}
@@ -386,7 +386,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
386386
if (A->getOption().matches(options::OPT__DASH_DASH)) {
387387
A->claim();
388388
for (StringRef Val : A->getValues())
389-
DAL->append(MakeInputArg(*DAL, *Opts, Val, false));
389+
DAL->append(MakeInputArg(*DAL, Opts, Val, false));
390390
continue;
391391
}
392392

@@ -395,14 +395,14 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
395395

396396
// Enforce -static if -miamcu is present.
397397
if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false))
398-
DAL->AddFlagArg(0, Opts->getOption(options::OPT_static));
398+
DAL->AddFlagArg(0, Opts.getOption(options::OPT_static));
399399

400400
// Add a default value of -mlinker-version=, if one was given and the user
401401
// didn't specify one.
402402
#if defined(HOST_LINK_VERSION)
403403
if (!Args.hasArg(options::OPT_mlinker_version_EQ) &&
404404
strlen(HOST_LINK_VERSION) > 0) {
405-
DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ),
405+
DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mlinker_version_EQ),
406406
HOST_LINK_VERSION);
407407
DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
408408
}
@@ -1592,16 +1592,17 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
15921592
if (llvm::is_contained(Flags, "-Xclang") || llvm::is_contained(Flags, "-cc1"))
15931593
DisableFlags &= ~options::NoDriverOption;
15941594

1595+
const llvm::opt::OptTable &Opts = getOpts();
15951596
StringRef Cur;
15961597
Cur = Flags.at(Flags.size() - 1);
15971598
StringRef Prev;
15981599
if (Flags.size() >= 2) {
15991600
Prev = Flags.at(Flags.size() - 2);
1600-
SuggestedCompletions = Opts->suggestValueCompletions(Prev, Cur);
1601+
SuggestedCompletions = Opts.suggestValueCompletions(Prev, Cur);
16011602
}
16021603

16031604
if (SuggestedCompletions.empty())
1604-
SuggestedCompletions = Opts->suggestValueCompletions(Cur, "");
1605+
SuggestedCompletions = Opts.suggestValueCompletions(Cur, "");
16051606

16061607
// If Flags were empty, it means the user typed `clang [tab]` where we should
16071608
// list all possible flags. If there was no value completion and the user
@@ -1619,7 +1620,7 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
16191620
// If the flag is in the form of "--autocomplete=-foo",
16201621
// we were requested to print out all option names that start with "-foo".
16211622
// For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
1622-
SuggestedCompletions = Opts->findByPrefix(Cur, DisableFlags);
1623+
SuggestedCompletions = Opts.findByPrefix(Cur, DisableFlags);
16231624

16241625
// We have to query the -W flags manually as they're not in the OptTable.
16251626
// TODO: Find a good way to add them to OptTable instead and them remove
@@ -2037,6 +2038,7 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,
20372038
// Construct a the list of inputs and their types.
20382039
void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
20392040
InputList &Inputs) const {
2041+
const llvm::opt::OptTable &Opts = getOpts();
20402042
// Track the current user specified (-x) input. We also explicitly track the
20412043
// argument used to set the type; we only want to claim the type when we
20422044
// actually use it, so we warn about unused -x arguments.
@@ -2160,15 +2162,15 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
21602162
StringRef Value = A->getValue();
21612163
if (DiagnoseInputExistence(Args, Value, types::TY_C,
21622164
/*TypoCorrect=*/false)) {
2163-
Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue());
2165+
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
21642166
Inputs.push_back(std::make_pair(types::TY_C, InputArg));
21652167
}
21662168
A->claim();
21672169
} else if (A->getOption().matches(options::OPT__SLASH_Tp)) {
21682170
StringRef Value = A->getValue();
21692171
if (DiagnoseInputExistence(Args, Value, types::TY_CXX,
21702172
/*TypoCorrect=*/false)) {
2171-
Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue());
2173+
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
21722174
Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));
21732175
}
21742176
A->claim();
@@ -2202,7 +2204,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
22022204
if (CCCIsCPP() && Inputs.empty()) {
22032205
// If called as standalone preprocessor, stdin is processed
22042206
// if no other input is present.
2205-
Arg *A = MakeInputArg(Args, *Opts, "-");
2207+
Arg *A = MakeInputArg(Args, Opts, "-");
22062208
Inputs.push_back(std::make_pair(types::TY_C, A));
22072209
}
22082210
}

clang/lib/Driver/DriverOptions.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,17 @@ class DriverOptTable : public OptTable {
3939

4040
}
4141

42-
std::unique_ptr<OptTable> clang::driver::createDriverOptTable() {
43-
auto Result = std::make_unique<DriverOptTable>();
44-
// Options.inc is included in DriverOptions.cpp, and calls OptTable's
45-
// addValues function.
46-
// Opt is a variable used in the code fragment in Options.inc.
47-
OptTable &Opt = *Result;
42+
const llvm::opt::OptTable &clang::driver::getDriverOptTable() {
43+
static const DriverOptTable *Table = []() {
44+
auto Result = std::make_unique<DriverOptTable>();
45+
// Options.inc is included in DriverOptions.cpp, and calls OptTable's
46+
// addValues function.
47+
// Opt is a variable used in the code fragment in Options.inc.
48+
OptTable &Opt = *Result;
4849
#define OPTTABLE_ARG_INIT
4950
#include "clang/Driver/Options.inc"
5051
#undef OPTTABLE_ARG_INIT
51-
return std::move(Result);
52+
return Result.release();
53+
}();
54+
return *Table;
5255
}

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3375,11 +3375,11 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
33753375
bool Success = true;
33763376

33773377
// Parse the arguments.
3378-
std::unique_ptr<OptTable> Opts = createDriverOptTable();
3378+
const OptTable &Opts = getDriverOptTable();
33793379
const unsigned IncludedFlagsBitmask = options::CC1Option;
33803380
unsigned MissingArgIndex, MissingArgCount;
3381-
InputArgList Args = Opts->ParseArgs(CommandLineArgs, MissingArgIndex,
3382-
MissingArgCount, IncludedFlagsBitmask);
3381+
InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,
3382+
MissingArgCount, IncludedFlagsBitmask);
33833383
LangOptions &LangOpts = *Res.getLangOpts();
33843384

33853385
// Check for missing argument error.
@@ -3393,7 +3393,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
33933393
for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
33943394
auto ArgString = A->getAsString(Args);
33953395
std::string Nearest;
3396-
if (Opts->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
3396+
if (Opts.findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
33973397
Diags.Report(diag::err_drv_unknown_argument) << ArgString;
33983398
else
33993399
Diags.Report(diag::err_drv_unknown_argument_with_suggestion)

clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,11 @@ CreateFrontendAction(CompilerInstance &CI) {
185185
bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
186186
// Honor -help.
187187
if (Clang->getFrontendOpts().ShowHelp) {
188-
std::unique_ptr<OptTable> Opts = driver::createDriverOptTable();
189-
Opts->PrintHelp(llvm::outs(), "clang -cc1 [options] file...",
190-
"LLVM 'Clang' Compiler: http://clang.llvm.org",
191-
/*Include=*/driver::options::CC1Option,
192-
/*Exclude=*/0, /*ShowAllAliases=*/false);
188+
driver::getDriverOptTable().PrintHelp(
189+
llvm::outs(), "clang -cc1 [options] file...",
190+
"LLVM 'Clang' Compiler: http://clang.llvm.org",
191+
/*Include=*/driver::options::CC1Option,
192+
/*Exclude=*/0, /*ShowAllAliases=*/false);
193193
return true;
194194
}
195195

clang/lib/Tooling/InterpolatingCompilationDatabase.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,17 +149,17 @@ struct TransferableCommand {
149149
// We parse each argument individually so that we can retain the exact
150150
// spelling of each argument; re-rendering is lossy for aliased flags.
151151
// E.g. in CL mode, /W4 maps to -Wall.
152-
auto OptTable = clang::driver::createDriverOptTable();
152+
auto &OptTable = clang::driver::getDriverOptTable();
153153
if (!OldArgs.empty())
154154
Cmd.CommandLine.emplace_back(OldArgs.front());
155155
for (unsigned Pos = 1; Pos < OldArgs.size();) {
156156
using namespace driver::options;
157157

158158
const unsigned OldPos = Pos;
159-
std::unique_ptr<llvm::opt::Arg> Arg(OptTable->ParseOneArg(
159+
std::unique_ptr<llvm::opt::Arg> Arg(OptTable.ParseOneArg(
160160
ArgList, Pos,
161-
/* Include */ClangCLMode ? CoreOption | CLOption : 0,
162-
/* Exclude */ClangCLMode ? 0 : CLOption));
161+
/* Include */ ClangCLMode ? CoreOption | CLOption : 0,
162+
/* Exclude */ ClangCLMode ? 0 : CLOption));
163163

164164
if (!Arg)
165165
continue;

clang/lib/Tooling/Tooling.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,7 @@ bool ToolInvocation::run() {
292292
const char *const BinaryName = Argv[0];
293293
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
294294
unsigned MissingArgIndex, MissingArgCount;
295-
std::unique_ptr<llvm::opt::OptTable> Opts = driver::createDriverOptTable();
296-
llvm::opt::InputArgList ParsedArgs = Opts->ParseArgs(
295+
llvm::opt::InputArgList ParsedArgs = driver::getDriverOptTable().ParseArgs(
297296
ArrayRef<const char *>(Argv).slice(1), MissingArgIndex, MissingArgCount);
298297
ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
299298
TextDiagnosticPrinter DiagnosticPrinter(

clang/tools/clang-check/ClangCheck.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,31 +52,34 @@ static cl::extrahelp MoreHelp(
5252
);
5353

5454
static cl::OptionCategory ClangCheckCategory("clang-check options");
55-
static std::unique_ptr<opt::OptTable> Options(createDriverOptTable());
55+
static const opt::OptTable &Options = getDriverOptTable();
5656
static cl::opt<bool>
57-
ASTDump("ast-dump", cl::desc(Options->getOptionHelpText(options::OPT_ast_dump)),
58-
cl::cat(ClangCheckCategory));
57+
ASTDump("ast-dump",
58+
cl::desc(Options.getOptionHelpText(options::OPT_ast_dump)),
59+
cl::cat(ClangCheckCategory));
5960
static cl::opt<bool>
60-
ASTList("ast-list", cl::desc(Options->getOptionHelpText(options::OPT_ast_list)),
61-
cl::cat(ClangCheckCategory));
61+
ASTList("ast-list",
62+
cl::desc(Options.getOptionHelpText(options::OPT_ast_list)),
63+
cl::cat(ClangCheckCategory));
6264
static cl::opt<bool>
63-
ASTPrint("ast-print",
64-
cl::desc(Options->getOptionHelpText(options::OPT_ast_print)),
65-
cl::cat(ClangCheckCategory));
65+
ASTPrint("ast-print",
66+
cl::desc(Options.getOptionHelpText(options::OPT_ast_print)),
67+
cl::cat(ClangCheckCategory));
6668
static cl::opt<std::string> ASTDumpFilter(
6769
"ast-dump-filter",
68-
cl::desc(Options->getOptionHelpText(options::OPT_ast_dump_filter)),
70+
cl::desc(Options.getOptionHelpText(options::OPT_ast_dump_filter)),
6971
cl::cat(ClangCheckCategory));
7072
static cl::opt<bool>
71-
Analyze("analyze", cl::desc(Options->getOptionHelpText(options::OPT_analyze)),
72-
cl::cat(ClangCheckCategory));
73+
Analyze("analyze",
74+
cl::desc(Options.getOptionHelpText(options::OPT_analyze)),
75+
cl::cat(ClangCheckCategory));
7376

7477
static cl::opt<bool>
75-
Fixit("fixit", cl::desc(Options->getOptionHelpText(options::OPT_fixit)),
76-
cl::cat(ClangCheckCategory));
78+
Fixit("fixit", cl::desc(Options.getOptionHelpText(options::OPT_fixit)),
79+
cl::cat(ClangCheckCategory));
7780
static cl::opt<bool> FixWhatYouCan(
7881
"fix-what-you-can",
79-
cl::desc(Options->getOptionHelpText(options::OPT_fix_what_you_can)),
82+
cl::desc(Options.getOptionHelpText(options::OPT_fix_what_you_can)),
8083
cl::cat(ClangCheckCategory));
8184

8285
namespace {

0 commit comments

Comments
 (0)