llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Victor Campos (vhscampos) <details> <summary>Changes</summary> This patch adds support for custom flags in the multilib YAML file. Details about this change can be found in this thread: https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058 --- Full diff: https://github.com/llvm/llvm-project/pull/110657.diff 3 Files Affected: - (modified) clang/include/clang/Driver/Multilib.h (+26-4) - (modified) clang/lib/Driver/Multilib.cpp (+71-9) - (added) clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml (+133) ``````````diff diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h index dbed70f4f9008f..333b1d2b555bd9 100644 --- a/clang/include/clang/Driver/Multilib.h +++ b/clang/include/clang/Driver/Multilib.h @@ -101,6 +101,25 @@ class Multilib { raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); +namespace custom_flag { +struct CustomFlagDeclaration; +using CustomFlagDeclarationPtr = std::shared_ptr<CustomFlagDeclaration>; + +struct CustomFlagValueDetail { + std::string Name; + std::optional<SmallVector<std::string>> ExtraBuildArgs; + CustomFlagDeclarationPtr Decl; +}; + +struct CustomFlagDeclaration { + std::string Name; + SmallVector<CustomFlagValueDetail> ValueList; + size_t DefaultValueIdx = ~0UL; +}; + +static constexpr StringRef Prefix = "-fmultilib-flag="; +} // namespace custom_flag + /// See also MultilibSetBuilder for combining multilibs into a set. class MultilibSet { public: @@ -120,15 +139,18 @@ class MultilibSet { private: multilib_list Multilibs; - std::vector<FlagMatcher> FlagMatchers; + SmallVector<FlagMatcher> FlagMatchers; + SmallVector<custom_flag::CustomFlagDeclarationPtr> CustomFlagDecls; IncludeDirsFunc IncludeCallback; IncludeDirsFunc FilePathsCallback; public: MultilibSet() = default; - MultilibSet(multilib_list &&Multilibs, - std::vector<FlagMatcher> &&FlagMatchers = {}) - : Multilibs(Multilibs), FlagMatchers(FlagMatchers) {} + MultilibSet( + multilib_list &&Multilibs, SmallVector<FlagMatcher> &&FlagMatchers = {}, + SmallVector<custom_flag::CustomFlagDeclarationPtr> &&CustomFlagDecls = {}) + : Multilibs(std::move(Multilibs)), FlagMatchers(std::move(FlagMatchers)), + CustomFlagDecls(std::move(CustomFlagDecls)) {} const multilib_list &getMultilibs() { return Multilibs; } diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp index c56417c6f6d0b0..81fe97517b0f91 100644 --- a/clang/lib/Driver/Multilib.cpp +++ b/clang/lib/Driver/Multilib.cpp @@ -11,7 +11,7 @@ #include "clang/Basic/Version.h" #include "clang/Driver/Driver.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" @@ -205,13 +205,20 @@ struct MultilibGroupSerialization { struct MultilibSetSerialization { llvm::VersionTuple MultilibVersion; - std::vector<MultilibGroupSerialization> Groups; - std::vector<MultilibSerialization> Multilibs; - std::vector<MultilibSet::FlagMatcher> FlagMatchers; + SmallVector<MultilibGroupSerialization> Groups; + SmallVector<MultilibSerialization> Multilibs; + SmallVector<MultilibSet::FlagMatcher> FlagMatchers; + SmallVector<custom_flag::CustomFlagDeclarationPtr> CustomFlagDeclarations; }; } // end anonymous namespace +LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSerialization) +LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibGroupSerialization) +LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSet::FlagMatcher) +LLVM_YAML_IS_SEQUENCE_VECTOR(custom_flag::CustomFlagValueDetail) +LLVM_YAML_IS_SEQUENCE_VECTOR(custom_flag::CustomFlagDeclarationPtr) + template <> struct llvm::yaml::MappingTraits<MultilibSerialization> { static void mapping(llvm::yaml::IO &io, MultilibSerialization &V) { io.mapOptional("Dir", V.Dir); @@ -259,11 +266,69 @@ template <> struct llvm::yaml::MappingTraits<MultilibSet::FlagMatcher> { } }; +template <> +struct llvm::yaml::MappingContextTraits<custom_flag::CustomFlagValueDetail, + llvm::SmallSet<std::string, 32>> { + static void mapping(llvm::yaml::IO &io, custom_flag::CustomFlagValueDetail &V, + llvm::SmallSet<std::string, 32> &) { + io.mapRequired("Name", V.Name); + io.mapOptional("ExtraBuildArgs", V.ExtraBuildArgs); + } + static std::string validate(IO &io, custom_flag::CustomFlagValueDetail &V, + llvm::SmallSet<std::string, 32> &NameSet) { + if (V.Name.empty()) + return "custom flag value requires a name"; + if (!NameSet.insert(V.Name).second) + return "duplicate custom flag value name: \"" + V.Name + "\""; + return {}; + } +}; + +template <> +struct llvm::yaml::MappingContextTraits<custom_flag::CustomFlagDeclarationPtr, + llvm::SmallSet<std::string, 32>> { + static void mapping(llvm::yaml::IO &io, + custom_flag::CustomFlagDeclarationPtr &V, + llvm::SmallSet<std::string, 32> &NameSet) { + assert(!V); + V = std::make_shared<custom_flag::CustomFlagDeclaration>(); + io.mapRequired("Name", V->Name); + io.mapRequired("Values", V->ValueList, NameSet); + std::string DefaultValueName; + io.mapRequired("Default", DefaultValueName); + + for (auto [Idx, Value] : llvm::enumerate(V->ValueList)) { + Value.Decl = V; + if (Value.Name == DefaultValueName) { + assert(V->DefaultValueIdx == ~0UL); + V->DefaultValueIdx = Idx; + } + } + } + static std::string validate(IO &io, custom_flag::CustomFlagDeclarationPtr &V, + llvm::SmallSet<std::string, 32> &) { + if (V->Name.empty()) + return "custom flag requires a name"; + if (V->ValueList.empty()) + return "custom flag must have at least one value"; + if (V->DefaultValueIdx >= V->ValueList.size()) + return "custom flag must have a default value"; + if (llvm::any_of(V->ValueList, [&V](const auto &Value) { + return !Value.Decl || Value.Decl != V; + })) + return "custom flag value missing reference to its custom flag " + "declaration"; + return {}; + } +}; + template <> struct llvm::yaml::MappingTraits<MultilibSetSerialization> { static void mapping(llvm::yaml::IO &io, MultilibSetSerialization &M) { io.mapRequired("MultilibVersion", M.MultilibVersion); io.mapRequired("Variants", M.Multilibs); io.mapOptional("Groups", M.Groups); + llvm::SmallSet<std::string, 32> NameSet; + io.mapOptionalWithContext("Flags", M.CustomFlagDeclarations, NameSet); io.mapOptional("Mappings", M.FlagMatchers); } static std::string validate(IO &io, MultilibSetSerialization &M) { @@ -292,10 +357,6 @@ template <> struct llvm::yaml::MappingTraits<MultilibSetSerialization> { } }; -LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSerialization) -LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibGroupSerialization) -LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSet::FlagMatcher) - llvm::ErrorOr<MultilibSet> MultilibSet::parseYaml(llvm::MemoryBufferRef Input, llvm::SourceMgr::DiagHandlerTy DiagHandler, @@ -323,7 +384,8 @@ MultilibSet::parseYaml(llvm::MemoryBufferRef Input, } } - return MultilibSet(std::move(Multilibs), std::move(MS.FlagMatchers)); + return MultilibSet(std::move(Multilibs), std::move(MS.FlagMatchers), + std::move(MS.CustomFlagDeclarations)); } LLVM_DUMP_METHOD void MultilibSet::dump() const { diff --git a/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml new file mode 100644 index 00000000000000..4d751cfe7c9edd --- /dev/null +++ b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml @@ -0,0 +1,133 @@ +# RUN: split-file %s %t + +# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/multilib-without-extra-build-args.yaml %s -### -o /dev/null 2>&1 \ +# RUN: | FileCheck %s +# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/multilib-with-extra-build-args.yaml %s -### -o /dev/null 2>&1 \ +# RUN: | FileCheck %s +# CHECK-NOT: error: + +# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-name.yaml %s -### -o /dev/null 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-NAME +# CHECK-MISSING-FLAG-NAME: error: custom flag requires a name + +# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-values.yaml %s -### -o /dev/null 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-VALUES +# CHECK-MISSING-FLAG-VALUES: error: custom flag must have at least one value + +# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-value-default.yaml %s -### -o /dev/null 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-VALUE-DEFAULT +# CHECK-MISSING-FLAG-VALUE-DEFAULT: error: custom flag must have a default value + +# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-value-name.yaml %s -### -o /dev/null 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-VALUE-NAME +# CHECK-MISSING-FLAG-VALUE-NAME: error: custom flag value requires a name + +# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/duplicate-flag-value-name.yaml %s -### -o /dev/null 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-DUPLICATE-FLAG-VALUE-NAME +# CHECK-DUPLICATE-FLAG-VALUE-NAME: error: duplicate custom flag value name: "value-name" +# CHECK-DUPLICATE-FLAG-VALUE-NAME-NEXT: - Name: value-name + +#--- multilib-without-extra-build-args.yaml +--- +MultilibVersion: 1.0 + +Variants: +- Dir: libc + Flags: [-fmultilib-flag=a] + +Flags: + - Name: flag + Values: + - Name: a + - Name: b + Default: a + +#--- multilib-with-extra-build-args.yaml +--- +MultilibVersion: 1.0 + +Variants: +- Dir: libc + Flags: [-fmultilib-flag=a] + +Flags: + - Name: flag + Values: + - Name: a + ExtraBuildArgs: [-DFEATURE_A] + - Name: b + ExtraBuildArgs: [-DFEATURE_B] + Default: a + +#--- missing-flag-name.yaml +--- +MultilibVersion: 1.0 + +Variants: +- Dir: libc + Flags: [-fmultilib-flag=a] + +Flags: + - Values: + - Name: a + Default: a + +#--- missing-flag-values.yaml +--- +MultilibVersion: 1.0 + +Variants: +- Dir: libc + Flags: [-fmultilib-flag=a] + +Flags: + - Name: flag + Values: + Default: a + +#--- missing-flag-value-default.yaml +--- +MultilibVersion: 1.0 + +Variants: +- Dir: libc + Flags: [-fmultilib-flag=a] + +Flags: + - Name: flag + Values: + - Name: a + Default: + +#--- missing-flag-value-name.yaml +--- +MultilibVersion: 1.0 + +Variants: +- Dir: libc + Flags: [-fmultilib-flag=a] + +Flags: + - Name: flag + Values: + - Name: + Default: a + +#--- duplicate-flag-value-name.yaml +--- +MultilibVersion: 1.0 + +Variants: +- Dir: libc + Flags: [-fmultilib-flag=value-name] + +Flags: + - Name: a + Values: + - Name: value-name + - Name: value-a + Default: value-name + - Name: b + Values: + - Name: value-name + Default: value-name `````````` </details> https://github.com/llvm/llvm-project/pull/110657 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits