Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:52

0001 //===- Multilib.h -----------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_CLANG_DRIVER_MULTILIB_H
0010 #define LLVM_CLANG_DRIVER_MULTILIB_H
0011 
0012 #include "clang/Basic/LLVM.h"
0013 #include "llvm/ADT/ArrayRef.h"
0014 #include "llvm/ADT/STLExtras.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include "llvm/ADT/StringSet.h"
0017 #include "llvm/Support/Compiler.h"
0018 #include "llvm/Support/SourceMgr.h"
0019 #include <cassert>
0020 #include <functional>
0021 #include <optional>
0022 #include <string>
0023 #include <utility>
0024 #include <vector>
0025 
0026 namespace clang {
0027 namespace driver {
0028 
0029 class Driver;
0030 
0031 /// This corresponds to a single GCC Multilib, or a segment of one controlled
0032 /// by a command line flag.
0033 /// See also MultilibBuilder for building a multilib by mutating it
0034 /// incrementally.
0035 class Multilib {
0036 public:
0037   using flags_list = std::vector<std::string>;
0038 
0039 private:
0040   std::string GCCSuffix;
0041   std::string OSSuffix;
0042   std::string IncludeSuffix;
0043   flags_list Flags;
0044 
0045   // Optionally, a multilib can be assigned a string tag indicating that it's
0046   // part of a group of mutually exclusive possibilities. If two or more
0047   // multilibs have the same non-empty value of ExclusiveGroup, then only the
0048   // last matching one of them will be selected.
0049   //
0050   // Setting this to the empty string is a special case, indicating that the
0051   // directory is not mutually exclusive with anything else.
0052   std::string ExclusiveGroup;
0053 
0054   // Some Multilib objects don't actually represent library directories you can
0055   // select. Instead, they represent failures of multilib selection, of the
0056   // form 'Sorry, we don't have any library compatible with these constraints'.
0057   std::optional<std::string> Error;
0058 
0059 public:
0060   /// GCCSuffix, OSSuffix & IncludeSuffix will be appended directly to the
0061   /// sysroot string so they must either be empty or begin with a '/' character.
0062   /// This is enforced with an assert in the constructor.
0063   Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {},
0064            StringRef IncludeSuffix = {}, const flags_list &Flags = flags_list(),
0065            StringRef ExclusiveGroup = {},
0066            std::optional<StringRef> Error = std::nullopt);
0067 
0068   /// Get the detected GCC installation path suffix for the multi-arch
0069   /// target variant. Always starts with a '/', unless empty
0070   const std::string &gccSuffix() const { return GCCSuffix; }
0071 
0072   /// Get the detected os path suffix for the multi-arch
0073   /// target variant. Always starts with a '/', unless empty
0074   const std::string &osSuffix() const { return OSSuffix; }
0075 
0076   /// Get the include directory suffix. Always starts with a '/', unless
0077   /// empty
0078   const std::string &includeSuffix() const { return IncludeSuffix; }
0079 
0080   /// Get the flags that indicate or contraindicate this multilib's use
0081   /// All elements begin with either '-' or '!'
0082   const flags_list &flags() const { return Flags; }
0083 
0084   /// Get the exclusive group label.
0085   const std::string &exclusiveGroup() const { return ExclusiveGroup; }
0086 
0087   LLVM_DUMP_METHOD void dump() const;
0088   /// print summary of the Multilib
0089   void print(raw_ostream &OS) const;
0090 
0091   /// Check whether the default is selected
0092   bool isDefault() const
0093   { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); }
0094 
0095   bool operator==(const Multilib &Other) const;
0096 
0097   bool isError() const { return Error.has_value(); }
0098 
0099   const std::string &getErrorMessage() const { return Error.value(); }
0100 };
0101 
0102 raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
0103 
0104 namespace custom_flag {
0105 struct Declaration;
0106 
0107 struct ValueDetail {
0108   std::string Name;
0109   std::optional<SmallVector<std::string>> MacroDefines;
0110   Declaration *Decl;
0111 };
0112 
0113 struct Declaration {
0114   std::string Name;
0115   SmallVector<ValueDetail> ValueList;
0116   std::optional<size_t> DefaultValueIdx;
0117 
0118   Declaration() = default;
0119   Declaration(const Declaration &);
0120   Declaration(Declaration &&);
0121   Declaration &operator=(const Declaration &);
0122   Declaration &operator=(Declaration &&);
0123 };
0124 
0125 static constexpr StringRef Prefix = "-fmultilib-flag=";
0126 } // namespace custom_flag
0127 
0128 /// See also MultilibSetBuilder for combining multilibs into a set.
0129 class MultilibSet {
0130 public:
0131   using multilib_list = std::vector<Multilib>;
0132   using const_iterator = multilib_list::const_iterator;
0133   using IncludeDirsFunc =
0134       std::function<std::vector<std::string>(const Multilib &M)>;
0135   using FilterCallback = llvm::function_ref<bool(const Multilib &)>;
0136 
0137   /// Uses regular expressions to simplify flags used for multilib selection.
0138   /// For example, we may wish both -mfloat-abi=soft and -mfloat-abi=softfp to
0139   /// be treated as -mfloat-abi=soft.
0140   struct FlagMatcher {
0141     std::string Match;
0142     std::vector<std::string> Flags;
0143   };
0144 
0145 private:
0146   multilib_list Multilibs;
0147   SmallVector<FlagMatcher> FlagMatchers;
0148   SmallVector<custom_flag::Declaration> CustomFlagDecls;
0149   IncludeDirsFunc IncludeCallback;
0150   IncludeDirsFunc FilePathsCallback;
0151 
0152 public:
0153   MultilibSet() = default;
0154   MultilibSet(multilib_list &&Multilibs,
0155               SmallVector<FlagMatcher> &&FlagMatchers = {},
0156               SmallVector<custom_flag::Declaration> &&CustomFlagDecls = {})
0157       : Multilibs(std::move(Multilibs)), FlagMatchers(std::move(FlagMatchers)),
0158         CustomFlagDecls(std::move(CustomFlagDecls)) {}
0159 
0160   const multilib_list &getMultilibs() { return Multilibs; }
0161 
0162   /// Filter out some subset of the Multilibs using a user defined callback
0163   MultilibSet &FilterOut(FilterCallback F);
0164 
0165   /// Add a completed Multilib to the set
0166   void push_back(const Multilib &M);
0167 
0168   const_iterator begin() const { return Multilibs.begin(); }
0169   const_iterator end() const { return Multilibs.end(); }
0170 
0171   /// Process custom flags from \p Flags and returns an expanded flags list and
0172   /// a list of macro defines.
0173   /// Returns a pair where:
0174   ///  - first: the new flags list including custom flags after processing.
0175   ///  - second: the extra macro defines to be fed to the driver.
0176   std::pair<Multilib::flags_list, SmallVector<StringRef>>
0177   processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
0178 
0179   /// Select compatible variants, \returns false if none are compatible
0180   bool select(const Driver &D, const Multilib::flags_list &Flags,
0181               llvm::SmallVectorImpl<Multilib> &,
0182               llvm::SmallVector<StringRef> * = nullptr) const;
0183 
0184   unsigned size() const { return Multilibs.size(); }
0185 
0186   /// Get the given flags plus flags found by matching them against the
0187   /// FlagMatchers and choosing the Flags of each accordingly. The select method
0188   /// calls this method so in most cases it's not necessary to call it directly.
0189   llvm::StringSet<> expandFlags(const Multilib::flags_list &) const;
0190 
0191   LLVM_DUMP_METHOD void dump() const;
0192   void print(raw_ostream &OS) const;
0193 
0194   MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) {
0195     IncludeCallback = std::move(F);
0196     return *this;
0197   }
0198 
0199   const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; }
0200 
0201   MultilibSet &setFilePathsCallback(IncludeDirsFunc F) {
0202     FilePathsCallback = std::move(F);
0203     return *this;
0204   }
0205 
0206   const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; }
0207 
0208   static llvm::ErrorOr<MultilibSet>
0209   parseYaml(llvm::MemoryBufferRef, llvm::SourceMgr::DiagHandlerTy = nullptr,
0210             void *DiagHandlerCtxt = nullptr);
0211 };
0212 
0213 raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
0214 
0215 } // namespace driver
0216 } // namespace clang
0217 
0218 #endif // LLVM_CLANG_DRIVER_MULTILIB_H