1//===--- Multilib.h ---------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef LLVM_CLANG_DRIVER_MULTILIB_H 11#define LLVM_CLANG_DRIVER_MULTILIB_H 12 13#include "clang/Basic/LLVM.h" 14#include "llvm/ADT/STLExtras.h" 15#include "llvm/Option/Option.h" 16#include <functional> 17#include <string> 18#include <vector> 19 20namespace clang { 21namespace driver { 22 23/// This corresponds to a single GCC Multilib, or a segment of one controlled 24/// by a command line flag 25class Multilib { 26public: 27 typedef std::vector<std::string> flags_list; 28 29private: 30 std::string GCCSuffix; 31 std::string OSSuffix; 32 std::string IncludeSuffix; 33 flags_list Flags; 34 35public: 36 Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "", 37 StringRef IncludeSuffix = ""); 38 39 /// \brief Get the detected GCC installation path suffix for the multi-arch 40 /// target variant. Always starts with a '/', unless empty 41 const std::string &gccSuffix() const { 42 assert(GCCSuffix.empty() || 43 (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1)); 44 return GCCSuffix; 45 } 46 /// Set the GCC installation path suffix. 47 Multilib &gccSuffix(StringRef S); 48 49 /// \brief Get the detected os path suffix for the multi-arch 50 /// target variant. Always starts with a '/', unless empty 51 const std::string &osSuffix() const { 52 assert(OSSuffix.empty() || 53 (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1)); 54 return OSSuffix; 55 } 56 /// Set the os path suffix. 57 Multilib &osSuffix(StringRef S); 58 59 /// \brief Get the include directory suffix. Always starts with a '/', unless 60 /// empty 61 const std::string &includeSuffix() const { 62 assert(IncludeSuffix.empty() || 63 (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1)); 64 return IncludeSuffix; 65 } 66 /// Set the include directory suffix 67 Multilib &includeSuffix(StringRef S); 68 69 /// \brief Get the flags that indicate or contraindicate this multilib's use 70 /// All elements begin with either '+' or '-' 71 const flags_list &flags() const { return Flags; } 72 flags_list &flags() { return Flags; } 73 74 /// Add a flag to the flags list 75 /// \p Flag must be a flag accepted by the driver with its leading '-' removed, 76 /// and replaced with either: 77 /// '-' which contraindicates using this multilib with that flag 78 /// or: 79 /// '+' which promotes using this multilib in the presence of that flag 80 /// otherwise '-print-multi-lib' will not emit them correctly. 81 Multilib &flag(StringRef F) { 82 assert(F.front() == '+' || F.front() == '-'); 83 Flags.push_back(F); 84 return *this; 85 } 86 87 LLVM_DUMP_METHOD void dump() const; 88 /// \brief print summary of the Multilib 89 void print(raw_ostream &OS) const; 90 91 /// Check whether any of the 'against' flags contradict the 'for' flags. 92 bool isValid() const; 93 94 /// Check whether the default is selected 95 bool isDefault() const 96 { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); } 97 98 bool operator==(const Multilib &Other) const; 99}; 100 101raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); 102 103class MultilibSet { 104public: 105 typedef std::vector<Multilib> multilib_list; 106 typedef multilib_list::iterator iterator; 107 typedef multilib_list::const_iterator const_iterator; 108 109 typedef std::function<std::vector<std::string>(const Multilib &M)> 110 IncludeDirsFunc; 111 112 typedef llvm::function_ref<bool(const Multilib &)> FilterCallback; 113 114private: 115 multilib_list Multilibs; 116 IncludeDirsFunc IncludeCallback; 117 IncludeDirsFunc FilePathsCallback; 118 119public: 120 MultilibSet() {} 121 122 /// Add an optional Multilib segment 123 MultilibSet &Maybe(const Multilib &M); 124 125 /// Add a set of mutually incompatible Multilib segments 126 MultilibSet &Either(const Multilib &M1, const Multilib &M2); 127 MultilibSet &Either(const Multilib &M1, const Multilib &M2, 128 const Multilib &M3); 129 MultilibSet &Either(const Multilib &M1, const Multilib &M2, 130 const Multilib &M3, const Multilib &M4); 131 MultilibSet &Either(const Multilib &M1, const Multilib &M2, 132 const Multilib &M3, const Multilib &M4, 133 const Multilib &M5); 134 MultilibSet &Either(ArrayRef<Multilib> Ms); 135 136 /// Filter out some subset of the Multilibs using a user defined callback 137 MultilibSet &FilterOut(FilterCallback F); 138 /// Filter out those Multilibs whose gccSuffix matches the given expression 139 MultilibSet &FilterOut(const char *Regex); 140 141 /// Add a completed Multilib to the set 142 void push_back(const Multilib &M); 143 144 /// Union this set of multilibs with another 145 void combineWith(const MultilibSet &MS); 146 147 /// Remove all of thie multilibs from the set 148 void clear() { Multilibs.clear(); } 149 150 iterator begin() { return Multilibs.begin(); } 151 const_iterator begin() const { return Multilibs.begin(); } 152 153 iterator end() { return Multilibs.end(); } 154 const_iterator end() const { return Multilibs.end(); } 155 156 /// Pick the best multilib in the set, \returns false if none are compatible 157 bool select(const Multilib::flags_list &Flags, Multilib &M) const; 158 159 unsigned size() const { return Multilibs.size(); } 160 161 LLVM_DUMP_METHOD void dump() const; 162 void print(raw_ostream &OS) const; 163 164 MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) { 165 IncludeCallback = std::move(F); 166 return *this; 167 } 168 const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; } 169 170 MultilibSet &setFilePathsCallback(IncludeDirsFunc F) { 171 FilePathsCallback = std::move(F); 172 return *this; 173 } 174 const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; } 175 176private: 177 /// Apply the filter to Multilibs and return the subset that remains 178 static multilib_list filterCopy(FilterCallback F, const multilib_list &Ms); 179 180 /// Apply the filter to the multilib_list, removing those that don't match 181 static void filterInPlace(FilterCallback F, multilib_list &Ms); 182}; 183 184raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS); 185} 186} 187 188#endif 189 190