12#include "llvm/ADT/SmallString.h"
13#include "llvm/ADT/StringMap.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Compiler.h"
16#include "llvm/Support/Error.h"
17#include "llvm/Support/ErrorHandling.h"
18#include "llvm/Support/Path.h"
19#include "llvm/Support/Regex.h"
20#include "llvm/Support/VersionTuple.h"
21#include "llvm/Support/YAMLParser.h"
22#include "llvm/Support/YAMLTraits.h"
23#include "llvm/Support/raw_ostream.h"
29using namespace driver;
30using namespace llvm::sys;
33 StringRef IncludeSuffix,
const flags_list &Flags)
34 : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix),
36 assert(GCCSuffix.empty() ||
37 (StringRef(GCCSuffix).front() ==
'/' && GCCSuffix.size() > 1));
38 assert(OSSuffix.empty() ||
39 (StringRef(OSSuffix).front() ==
'/' && OSSuffix.size() > 1));
40 assert(IncludeSuffix.empty() ||
41 (StringRef(IncludeSuffix).front() ==
'/' && IncludeSuffix.size() > 1));
49 if (GCCSuffix.empty())
52 OS << StringRef(GCCSuffix).drop_front();
55 for (StringRef Flag : Flags) {
56 if (Flag.front() ==
'-')
57 OS <<
"@" << Flag.substr(1);
64 llvm::StringSet<> MyFlags;
65 for (
const auto &Flag : Flags)
68 for (
const auto &Flag : Other.Flags)
69 if (!MyFlags.contains(Flag))
90 llvm::erase_if(Multilibs, F);
100 llvm::copy_if(Multilibs, std::back_inserter(Selected),
102 for (
const std::string &F : M.
flags())
103 if (!FlagSet.contains(F))
107 return !Selected.empty();
113 for (
const auto &F : InFlags)
116 std::string RegexString(M.Match);
119 if (!StringRef(M.Match).starts_with(
"^"))
120 RegexString.insert(RegexString.begin(),
'^');
121 if (!StringRef(M.Match).ends_with(
"$"))
122 RegexString.push_back(
'$');
124 const llvm::Regex Regex(RegexString);
125 assert(Regex.isValid());
126 if (llvm::find_if(InFlags, [&Regex](StringRef F) {
127 return Regex.match(F);
128 }) != InFlags.end()) {
129 Result.insert(M.Flags.begin(), M.Flags.end());
138static const VersionTuple MultilibVersionCurrent(1, 0);
140struct MultilibSerialization {
142 std::vector<std::string> Flags;
145struct MultilibSetSerialization {
146 llvm::VersionTuple MultilibVersion;
147 std::vector<MultilibSerialization> Multilibs;
148 std::vector<MultilibSet::FlagMatcher> FlagMatchers;
153template <>
struct llvm::yaml::MappingTraits<MultilibSerialization> {
154 static void mapping(llvm::yaml::IO &io, MultilibSerialization &
V) {
155 io.mapRequired(
"Dir",
V.Dir);
156 io.mapRequired(
"Flags",
V.Flags);
158 static std::string
validate(IO &io, MultilibSerialization &
V) {
159 if (StringRef(
V.Dir).starts_with(
"/"))
160 return "paths must be relative but \"" +
V.Dir +
"\" starts with \"/\"";
161 return std::string{};
165template <>
struct llvm::yaml::MappingTraits<
MultilibSet::FlagMatcher> {
167 io.mapRequired(
"Match", M.
Match);
168 io.mapRequired(
"Flags", M.
Flags);
171 llvm::Regex Regex(M.
Match);
172 std::string RegexError;
173 if (!Regex.isValid(RegexError))
176 return "value required for 'Flags'";
177 return std::string{};
181template <>
struct llvm::yaml::MappingTraits<MultilibSetSerialization> {
182 static void mapping(llvm::yaml::IO &io, MultilibSetSerialization &M) {
183 io.mapRequired(
"MultilibVersion", M.MultilibVersion);
184 io.mapRequired(
"Variants", M.Multilibs);
185 io.mapOptional(
"Mappings", M.FlagMatchers);
187 static std::string
validate(IO &io, MultilibSetSerialization &M) {
188 if (M.MultilibVersion.empty())
189 return "missing required key 'MultilibVersion'";
190 if (M.MultilibVersion.getMajor() != MultilibVersionCurrent.getMajor())
191 return "multilib version " + M.MultilibVersion.getAsString() +
193 if (M.MultilibVersion.getMinor() > MultilibVersionCurrent.getMinor())
194 return "multilib version " + M.MultilibVersion.getAsString() +
196 return std::string{};
200LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSerialization)
203llvm::ErrorOr<MultilibSet>
205 llvm::SourceMgr::DiagHandlerTy DiagHandler,
206 void *DiagHandlerCtxt) {
207 MultilibSetSerialization MS;
208 llvm::yaml::Input YamlInput(Input,
nullptr, DiagHandler, DiagHandlerCtxt);
210 if (YamlInput.error())
211 return YamlInput.error();
214 Multilibs.reserve(MS.Multilibs.size());
215 for (
const auto &M : MS.Multilibs) {
219 Multilibs.emplace_back(Dir, Dir, Dir, M.Flags);
222 return MultilibSet(std::move(Multilibs), std::move(MS.FlagMatchers));
230 for (
const auto &M : *
this)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines version macros and version-related utility functions for Clang.
See also MultilibSetBuilder for combining multilibs into a set.
bool select(const Multilib::flags_list &Flags, llvm::SmallVector< Multilib > &) const
Select compatible variants,.
LLVM_DUMP_METHOD void dump() const
llvm::function_ref< bool(const Multilib &)> FilterCallback
static llvm::ErrorOr< MultilibSet > parseYaml(llvm::MemoryBufferRef, llvm::SourceMgr::DiagHandlerTy=nullptr, void *DiagHandlerCtxt=nullptr)
void print(raw_ostream &OS) const
MultilibSet & FilterOut(FilterCallback F)
Filter out some subset of the Multilibs using a user defined callback.
std::vector< Multilib > multilib_list
llvm::StringSet expandFlags(const Multilib::flags_list &) const
Get the given flags plus flags found by matching them against the FlagMatchers and choosing the Flags...
void push_back(const Multilib &M)
Add a completed Multilib to the set.
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
Multilib(StringRef GCCSuffix={}, StringRef OSSuffix={}, StringRef IncludeSuffix={}, const flags_list &Flags=flags_list())
GCCSuffix, OSSuffix & IncludeSuffix will be appended directly to the sysroot string so they must eith...
const std::string & gccSuffix() const
Get the detected GCC installation path suffix for the multi-arch target variant.
const std::string & osSuffix() const
Get the detected os path suffix for the multi-arch target variant.
const flags_list & flags() const
Get the flags that indicate or contraindicate this multilib's use All elements begin with either '-' ...
std::vector< std::string > flags_list
const std::string & includeSuffix() const
Get the include directory suffix.
LLVM_DUMP_METHOD void dump() const
void print(raw_ostream &OS) const
print summary of the Multilib
bool operator==(const Multilib &Other) const
raw_ostream & operator<<(raw_ostream &OS, const Multilib &M)
@ Result
The result type of a method or function.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
Uses regular expressions to simplify flags used for multilib selection.
std::vector< std::string > Flags
static void mapping(llvm::yaml::IO &io, MultilibSerialization &V)
static std::string validate(IO &io, MultilibSerialization &V)
static void mapping(llvm::yaml::IO &io, MultilibSetSerialization &M)
static std::string validate(IO &io, MultilibSetSerialization &M)
static std::string validate(IO &io, MultilibSet::FlagMatcher &M)
static void mapping(llvm::yaml::IO &io, MultilibSet::FlagMatcher &M)