llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
@llvm/pr-subscribers-clang-codegen
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
`OptionsStruct<..., perContext = true>` lets each LLVMContext hold its
own values of a library's options, so that two contexts in one process
can compile with different values. The static member `Global` becomes
private, and readers call `Ctx.getLibraryOptions().get<T>()`, which
returns the context's copy, (temporary fallback) or `Global` if it has
none. InstCombine is the first such library.
The new cl::parseCommandLineOptions sets per-context libraries' options
in the given cl::LibraryOptionsContext instead of Global. opt parses
into its LLVMContext; clang -cc1 parses -mllvm into its CompilerInstance
and replays the arguments into each code generation LLVMContext. An
embedder calls set({"-x=v"}), which dispatches through the cl::
registry.
https://discourse.llvm.org/t/rfc-declare-library-command-line-options-in-tablegen-one-struct-per-library/91877
LLM-aided
---
Patch is 38.39 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/231407.diff
25 Files Affected:
- (modified) clang/include/clang/Frontend/CompilerInstance.h (+9)
- (modified) clang/lib/CIR/FrontendAction/CIRGenAction.cpp (+2)
- (modified) clang/lib/CodeGen/CodeGenAction.cpp (+2)
- (modified) clang/lib/Frontend/CompilerInstance.cpp (+3-2)
- (added) clang/test/CIR/CodeGen/mllvm-library-options.c (+17)
- (added) clang/test/CodeGen/mllvm-library-options.ll (+21)
- (modified) llvm/include/llvm/IR/LLVMContext.h (+7)
- (modified) llvm/include/llvm/Option/LibraryOptions.h (+23-13)
- (modified) llvm/include/llvm/Option/LibraryOptions.td (+3-1)
- (modified) llvm/include/llvm/Support/CommandLine.h (+30-5)
- (added) llvm/include/llvm/Support/LibraryOptionsContext.h (+64)
- (modified) llvm/lib/IR/LLVMContext.cpp (+4)
- (modified) llvm/lib/IR/LLVMContextImpl.h (+3)
- (modified) llvm/lib/Option/LibraryOptions.cpp (+2-2)
- (modified) llvm/lib/Support/CommandLine.cpp (+82-21)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCLOptions.td (+1-1)
- (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+3-1)
- (modified) llvm/tools/opt/optdriver.cpp (+4-4)
- (modified) llvm/unittests/IR/CMakeLists.txt (+2)
- (added) llvm/unittests/IR/LibraryOptionsContextTest.cpp (+69)
- (modified) llvm/unittests/Option/LibraryOptionsTest.cpp (+49-7)
- (modified) llvm/unittests/Support/CommandLineTest.cpp (+3-1)
- (modified) llvm/utils/TableGen/Basic/OptionParserEmitter.cpp (+11-4)
- (modified) llvm/utils/gn/secondary/llvm/unittests/IR/BUILD.gn (+2)
- (modified) utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel (+1)
``````````diff
diff --git a/clang/include/clang/Frontend/CompilerInstance.h
b/clang/include/clang/Frontend/CompilerInstance.h
index b87dd037480d6..bceb85f6e923b 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -26,6 +26,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LibraryOptionsContext.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/VirtualOutputBackend.h"
#include <cassert>
@@ -147,6 +148,10 @@ class CompilerInstance : public ModuleLoader {
/// The frontend timer.
std::unique_ptr<llvm::Timer> FrontendTimer;
+ /// The -mllvm options of per-context libraries, which every LLVMContext that
+ /// compiles for this instance receives.
+ llvm::cl::LibraryOptionsContext LibraryOptions;
+
/// The ASTReader, if one exists.
IntrusiveRefCntPtr<ASTReader> TheASTReader;
@@ -269,6 +274,10 @@ class CompilerInstance : public ModuleLoader {
/// This should be called after plugins are loaded and before ExecuteAction.
void parseLLVMArgs();
+ const llvm::cl::LibraryOptionsContext &getLibraryOptions() const {
+ return LibraryOptions;
+ }
+
/// @}
/// @name Compiler Invocation and Options
/// @{
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index 71a7a17146af3..a04aa51e163af 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -35,6 +35,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Linker/Linker.h"
+#include "llvm/Support/LibraryOptionsContext.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -367,6 +368,7 @@ CIRGenAction::CIRGenAction(OutputType Act,
mlir::MLIRContext *MLIRCtx)
CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
bool CIRGenAction::BeginSourceFileAction(CompilerInstance &CI) {
+ cantFail(Ctx->getLibraryOptions().set(CI.getLibraryOptions().args()));
if (clang::loadLinkModules(CI, *Ctx, LinkModules))
return false;
return ASTFrontendAction::BeginSourceFileAction(CI);
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp
b/clang/lib/CodeGen/CodeGenAction.cpp
index 1abd8b0455a19..22925cc55f495 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -42,6 +42,7 @@
#include "llvm/LTO/LTOBackend.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Pass.h"
+#include "llvm/Support/LibraryOptionsContext.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
@@ -366,6 +367,7 @@ CodeGenerator *CodeGenAction::getCodeGenerator() const {
}
bool CodeGenAction::BeginSourceFileAction(CompilerInstance &CI) {
+ cantFail(VMContext->getLibraryOptions().set(CI.getLibraryOptions().args()));
if (CI.getFrontendOpts().GenReducedBMI)
CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
return ASTFrontendAction::BeginSourceFileAction(CI);
diff --git a/clang/lib/Frontend/CompilerInstance.cpp
b/clang/lib/Frontend/CompilerInstance.cpp
index b09c9a9f5a5be..f122208d6b4c8 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1143,8 +1143,9 @@ void CompilerInstance::parseLLVMArgs() {
for (unsigned i = 0; i != NumArgs; ++i)
Args[i + 1] = getFrontendOpts().LLVMArgs[i].c_str();
Args[NumArgs + 1] = nullptr;
- llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get(), /*Overview=*/"",
- /*Errs=*/nullptr,
+ llvm::cl::parseCommandLineOptions(LibraryOptions,
+ ArrayRef(Args.get(), NumArgs + 1),
+ /*Overview=*/"", /*Errs=*/nullptr,
/*VFS=*/&getVirtualFileSystem());
}
}
diff --git a/clang/test/CIR/CodeGen/mllvm-library-options.c
b/clang/test/CIR/CodeGen/mllvm-library-options.c
new file mode 100644
index 0000000000000..4f584b4058a81
--- /dev/null
+++ b/clang/test/CIR/CodeGen/mllvm-library-options.c
@@ -0,0 +1,17 @@
+// -mllvm options of per-context libraries reach the LLVMContext that CIR is
+// lowered into.
+// RUN: %clang_cc1 -triple x86_64 -O1 -fclangir -emit-llvm %s -o - | FileCheck
%s --check-prefixes=CHECK,SINK
+// RUN: %clang_cc1 -triple x86_64 -O1 -fclangir -emit-llvm -mllvm
-instcombine-code-sinking=0 %s -o - | FileCheck %s --check-prefixes=CHECK,NOSINK
+
+void use(int);
+
+// CHECK-LABEL: define {{.*}} @f(
+// SINK-NOT: sdiv
+// NOSINK: sdiv
+// CHECK: br i1
+// SINK: sdiv
+void f(int c, int a, int b) {
+ int d = a / b;
+ if (c)
+ use(d);
+}
diff --git a/clang/test/CodeGen/mllvm-library-options.ll
b/clang/test/CodeGen/mllvm-library-options.ll
new file mode 100644
index 0000000000000..a4938f811537c
--- /dev/null
+++ b/clang/test/CodeGen/mllvm-library-options.ll
@@ -0,0 +1,21 @@
+;; -mllvm options of per-context libraries reach the LLVMContext that compiles.
+; RUN: %clang_cc1 -O1 -emit-llvm %s -o - | FileCheck %s
--check-prefixes=CHECK,SINK
+; RUN: %clang_cc1 -O1 -emit-llvm -mllvm -instcombine-code-sinking=0 %s -o - |
FileCheck %s --check-prefixes=CHECK,NOSINK
+
+; CHECK-LABEL: define {{.*}} @f(
+; NOSINK-NEXT: entry:
+; NOSINK-NEXT: = sdiv
+; CHECK: {{^}}t:
+; SINK-NEXT: = sdiv
+define void @f(i1 %c, i32 %a, i32 %b) {
+entry:
+ %d = sdiv i32 %a, %b
+ br i1 %c, label %t, label %e
+t:
+ call void @use(i32 %d)
+ ret void
+e:
+ ret void
+}
+
+declare void @use(i32)
diff --git a/llvm/include/llvm/IR/LLVMContext.h
b/llvm/include/llvm/IR/LLVMContext.h
index ced9b9227538e..be0d27bacf3e4 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -32,6 +32,9 @@ class Instruction;
class LLVMContextImpl;
class Module;
class OptPassGate;
+namespace cl {
+class LibraryOptionsContext;
+} // namespace cl
template <typename T> class SmallVectorImpl;
template <typename T> class StringMapEntry;
class StringRef;
@@ -329,6 +332,10 @@ class LLVMContext {
/// LLVMContext is used by compilation.
LLVM_ABI void setOptPassGate(OptPassGate &);
+ /// The library options this context reads in place of their process-wide
+ /// values.
+ LLVM_ABI cl::LibraryOptionsContext &getLibraryOptions() const;
+
/// Get or set the current "default" target CPU (target-cpu function
/// attribute). The intent is that compiler frontends will set this to a
value
/// that reflects the attribute that a function would get "by default"
without
diff --git a/llvm/include/llvm/Option/LibraryOptions.h
b/llvm/include/llvm/Option/LibraryOptions.h
index 8b5c34525fa7c..19df88f77e586 100644
--- a/llvm/include/llvm/Option/LibraryOptions.h
+++ b/llvm/include/llvm/Option/LibraryOptions.h
@@ -27,6 +27,7 @@
#include "llvm/Support/Compiler.h"
#include <optional>
#include <type_traits>
+#include <utility>
namespace llvm {
namespace opt {
@@ -118,23 +119,36 @@ class LLVM_ABI LibraryOptTable : public OptTable {
~LibraryOptTable() override;
};
-/// Connects an options struct to cl::ParseCommandLineOptions.
+/// Connects options struct T to cl::ParseCommandLineOptions and
+/// cl::LibraryOptionsContext.
class LLVM_ABI LibraryOptionsParser final : public cl::LibraryOptions {
public:
- using ApplyFn = bool (*)(const Arg &, BumpPtrAllocator &);
- using TableFn = const OptTable &(*)();
- LibraryOptionsParser(TableFn Table, ApplyFn Apply, void (*Reset)())
- : Table(Table), Apply(Apply), Reset(Reset) {}
+ template <typename T>
+ explicit LibraryOptionsParser(std::in_place_type_t<T>)
+ : LibraryOptions(T::PerContext), Table(T::optTable), Global(&T::Global),
+ Apply([](void *Opts, const Arg &A, BumpPtrAllocator &Alloc) {
+ return static_cast<T *>(Opts)->apply(A, Alloc);
+ }),
+ Copy([](BumpPtrAllocator &Alloc) -> void * {
+ return new (Alloc) T(T::Global);
+ }),
+ Reset([] { T::Global = T(); }) {}
void forEachOption(
function_ref<void(StringRef, StringRef, StringRef)> Fn) const override;
- Error parse(ArrayRef<const char *> Args, unsigned &Consumed,
+ Error parse(void *Opts, ArrayRef<const char *> Args, unsigned &Consumed,
BumpPtrAllocator &Alloc) override;
+ void *global() override { return Global; }
+ void *copyGlobal(BumpPtrAllocator &Alloc) const override {
+ return Copy(Alloc);
+ }
void reset() override { Reset(); }
private:
- TableFn Table;
- ApplyFn Apply;
+ const OptTable &(*Table)();
+ void *Global;
+ bool (*Apply)(void *Opts, const Arg &A, BumpPtrAllocator &Alloc);
+ void *(*Copy)(BumpPtrAllocator &Alloc);
void (*Reset)();
};
@@ -144,11 +158,7 @@ class LLVM_ABI LibraryOptionsParser final : public
cl::LibraryOptions {
template <typename T> class RegisterLibraryOptions {
static_assert(std::is_trivially_destructible_v<T>,
"an options struct must not need an exit-time destructor");
- LibraryOptionsParser Parser{T::optTable,
- [](const Arg &A, BumpPtrAllocator &Alloc) {
- return T::Global.apply(A, Alloc);
- },
- [] { T::Global = T(); }};
+ LibraryOptionsParser Parser{std::in_place_type<T>};
public:
RegisterLibraryOptions() { cl::addLibraryOptions(Parser); }
diff --git a/llvm/include/llvm/Option/LibraryOptions.td
b/llvm/include/llvm/Option/LibraryOptions.td
index d901f8027f702..ab027c056831e 100644
--- a/llvm/include/llvm/Option/LibraryOptions.td
+++ b/llvm/include/llvm/Option/LibraryOptions.td
@@ -17,9 +17,11 @@
include "llvm/Option/OptParser.td"
// A row whose spelling starts with prefix names its member without it.
-class OptionsStruct<string namespace = "llvm", string prefix = ""> {
+// perContext makes Global private; read through
cl::LibraryOptionsContext::get.
+class OptionsStruct<string namespace = "llvm", string prefix = "", bit
perContext = false> {
string Namespace = namespace;
string MemberPrefix = prefix;
+ bit PerContext = perContext;
}
// The builds an option exists in, as a preprocessor expression.
diff --git a/llvm/include/llvm/Support/CommandLine.h
b/llvm/include/llvm/Support/CommandLine.h
index bc7059244461e..1b3e3745ce724 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -50,6 +50,8 @@ class Error;
/// It is intentionally a short name to make qualified usage concise.
namespace cl {
+class LibraryOptionsContext;
+
//===----------------------------------------------------------------------===//
// Command line option processing entry point.
//
@@ -70,6 +72,15 @@ LLVM_ABI bool ParseCommandLineOptions(int argc, const char
*const *argv,
vfs::FileSystem *VFS = nullptr,
const char *EnvVar = nullptr);
+// Like ParseCommandLineOptions, but sets the library registered options
+// as per-context in LibraryOptions rather than in their global().
+LLVM_ABI bool parseCommandLineOptions(LibraryOptionsContext &LibraryOptions,
+ ArrayRef<const char *> Args,
+ StringRef Overview = "",
+ raw_ostream *Errs = nullptr,
+ vfs::FileSystem *VFS = nullptr,
+ const char *EnvVar = nullptr);
+
// Function pointer type for printing version information.
using VersionPrinterTy = std::function<void(raw_ostream &)>;
@@ -2176,18 +2187,32 @@ class LLVM_ABI LibraryOptions {
Fn) const = 0;
/// Parses the option spelled by Args[0], which may take Args[1] as its
- /// value, and sets \p Consumed to the number of arguments it spans. The
- /// strings in \p Args and the memory from \p Alloc remain valid until
- /// reset().
- virtual Error parse(ArrayRef<const char *> Args, unsigned &Consumed,
- BumpPtrAllocator &Alloc) = 0;
+ /// value, into \p Opts, which is global() or a copy of it, and sets
+ /// \p Consumed to the number of arguments it spans. The strings in \p Args
+ /// and the memory from \p Alloc remain valid as long as \p Opts is used.
+ virtual Error parse(void *Opts, ArrayRef<const char *> Args,
+ unsigned &Consumed, BumpPtrAllocator &Alloc) = 0;
+
+ /// Returns the values that ParseCommandLineOptions sets.
+ virtual void *global() = 0;
+
+ /// Returns a copy of global() allocated from \p Alloc.
+ virtual void *copyGlobal(BumpPtrAllocator &Alloc) const = 0;
/// Restores the default values.
virtual void reset() = 0;
+ /// Whether every reader of the options goes through a context's
+ /// LibraryOptionsContext, so that they need not be set in global().
+ bool isPerContext() const { return PerContext; }
+
protected:
+ explicit LibraryOptions(bool PerContext = false) : PerContext(PerContext) {}
// Registrations are static and never destroyed through this class.
~LibraryOptions() = default;
+
+private:
+ bool PerContext;
};
/// Makes ParseCommandLineOptions recognize \p L's options. A name that is also
diff --git a/llvm/include/llvm/Support/LibraryOptionsContext.h
b/llvm/include/llvm/Support/LibraryOptionsContext.h
new file mode 100644
index 0000000000000..150a8c1d5a771
--- /dev/null
+++ b/llvm/include/llvm/Support/LibraryOptionsContext.h
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_LIBRARYOPTIONSCONTEXT_H
+#define LLVM_SUPPORT_LIBRARYOPTIONSCONTEXT_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class Error;
+
+namespace cl {
+
+class LibraryOptions;
+
+// Values of library options that override their global() in one compilation
+// context, such as an LLVMContext.
+class LLVM_ABI LibraryOptionsContext {
+public:
+ // Sets the library options that Args spell, e.g. {"-x=v"}. A library's
values
+ // start as a copy of its global(), and later calls add to them. Fails at the
+ // first argument that is not a library option or has an invalid value.
+ //
+ // Strings copied from global() die with ResetAllOptionOccurrences. The first
+ // call (or ParseCommandLineOptions) indexes the registry, which is not
+ // thread-safe.
+ Error set(ArrayRef<const char *> Args);
+
+ // Parses the option of L that Args[0] spells, as set() does.
+ Error parse(LibraryOptions &L, ArrayRef<const char *> Args,
+ unsigned &Consumed);
+
+ // The arguments set so far, for replaying into another context.
+ ArrayRef<const char *> args() const { return Args; }
+
+ // T's values, or T::Global if there are none.
+ template <typename T> const T &get() const {
+ if (const void *Opts = Values.lookup(&T::Global))
+ return *static_cast<const T *>(Opts);
+ // TODO: Return the defaults once cl::ParseCommandLineOptions callers have
+ // migrated to parseCommandLineOptions and no longer set T::Global.
+ return T::Global;
+ }
+
+private:
+ DenseMap<const void *, void *> Values;
+ SmallVector<const char *, 0> Args;
+ BumpPtrAllocator Alloc;
+};
+
+} // namespace cl
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_LIBRARYOPTIONSCONTEXT_H
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 1fcdd3bc4c142..fb3b4bd8b206f 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -357,6 +357,10 @@ void LLVMContext::setOptPassGate(OptPassGate& OPG) {
pImpl->setOptPassGate(OPG);
}
+cl::LibraryOptionsContext &LLVMContext::getLibraryOptions() const {
+ return pImpl->LibraryOptions;
+}
+
const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const {
return pImpl->DiagHandler.get();
}
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 74a73664473b0..d02d57e4c0197 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -40,6 +40,7 @@
#include "llvm/IR/Value.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/LibraryOptionsContext.h"
#include "llvm/Support/StringSaver.h"
#include <algorithm>
#include <cassert>
@@ -1951,6 +1952,8 @@ class LLVMContextImpl {
std::string DefaultTargetCPU;
std::string DefaultTargetFeatures;
+ cl::LibraryOptionsContext LibraryOptions;
+
/// The next available source atom group number. The front end is responsible
/// for assigning source atom numbers, but certain optimisations need to
/// assign new group numbers to a set of instructions. Most often code
diff --git a/llvm/lib/Option/LibraryOptions.cpp
b/llvm/lib/Option/LibraryOptions.cpp
index cfcb82273eb6d..e5848a0498f23 100644
--- a/llvm/lib/Option/LibraryOptions.cpp
+++ b/llvm/lib/Option/LibraryOptions.cpp
@@ -34,7 +34,7 @@ void LibraryOptionsParser::forEachOption(
}
}
-Error LibraryOptionsParser::parse(ArrayRef<const char *> Args,
+Error LibraryOptionsParser::parse(void *Opts, ArrayRef<const char *> Args,
unsigned &Consumed, BumpPtrAllocator &Alloc)
{
InputArgList List(Args.begin(), Args.end());
Consumed = 0;
@@ -45,7 +45,7 @@ Error LibraryOptionsParser::parse(ArrayRef<const char *> Args,
"' requires an argument");
if (A->getOption().getKind() == Option::UnknownClass)
return createStringError("unknown argument '" + Twine(Args[0]) + "'");
- if (!Apply(*A, Alloc))
+ if (!Apply(Opts, *A, Alloc))
return createStringError("invalid value '" + Twine(A->getValue()) +
"' in '" + A->getAsString(List) + "'");
return Error::success();
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 1cb5fccb07a1b..31f07e114cace 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -35,6 +35,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LibraryOptionsContext.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -189,7 +190,8 @@ class CommandLineParser {
bool ParseCommandLineOptions(int argc, const char *const *argv,
StringRef Overview, raw_ostream *Errs = nullptr,
- vfs::FileSystem *VFS = nullptr);
+ vfs::FileSystem *VFS = nullptr,
+ LibraryOptionsContext *Context = nullptr);
void forEachSubCommand(Option &Opt, function_ref<void(SubCommand &)> Action)
{
if (Opt.Subs.empty()) {
@@ -440,6 +442,26 @@ static CommandLineParser &globalParser() {
return *GlobalParser;
}
+// Parses the library option spelled by Args[0], which takes at most one
+// separate value, into Opts. Opts may refer to the arguments, so they are
+// copied into Alloc, and appended to Record if given.
+static Error
+parseLibraryOption(LibraryOptions &L, void *Opts, ArrayRef<const char *> Args,
+ unsigned &Consumed, BumpPtrAllocator &Alloc,
+ SmallVectorImpl<const char *> *Record = nullptr) {
+ StringSaver Saver(Alloc);
+ const char *Saved[2];
+ unsigned NumArgs = std::min<size_t>(Args.size(), 2);
+ for (unsigned J = 0; J != NumArgs; ++J)
+ Saved[J] = Saver.save(Args[J]).data();
+ Consumed = 1;
+ if (Error E = L.parse(Opts, ArrayRef(Saved, NumArgs), Consumed, Alloc))
+ return E;
+ if (Record)
+ Record->append(Saved, Saved + Consumed);
+ return Error::success();
+}
+
template <typename T, T TrueVal, T FalseVal>
static bool parseBool(Option &O, StringRef ArgName, StringRef Arg, T &Value) {
// ProvideOption passes a null Arg for a bare -flag (treated as true) and an
@@ -1424,14 +1446,15 @@ Error ExpansionContext::readConfigFile(StringRef
CfgFile,
}
static void ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/231407
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits