Home | History | Annotate | Download | only in Driver
      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 CLANG_LIB_DRIVER_MULTILIB_H_
     11 #define CLANG_LIB_DRIVER_MULTILIB_H_
     12 
     13 #include "clang/Basic/LLVM.h"
     14 #include "llvm/ADT/Triple.h"
     15 #include "llvm/Option/Option.h"
     16 #include <string>
     17 #include <vector>
     18 
     19 namespace clang {
     20 namespace driver {
     21 
     22 /// This corresponds to a single GCC Multilib, or a segment of one controlled
     23 /// by a command line flag
     24 class Multilib {
     25 public:
     26   typedef std::vector<std::string> flags_list;
     27 
     28 private:
     29   std::string GCCSuffix;
     30   std::string OSSuffix;
     31   std::string IncludeSuffix;
     32   flags_list Flags;
     33 
     34 public:
     35   Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "",
     36            StringRef IncludeSuffix = "");
     37 
     38   /// \brief Get the detected GCC installation path suffix for the multi-arch
     39   /// target variant. Always starts with a '/', unless empty
     40   const std::string &gccSuffix() const {
     41     assert(GCCSuffix.empty() ||
     42            (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
     43     return GCCSuffix;
     44   }
     45   /// Set the GCC installation path suffix.
     46   Multilib &gccSuffix(StringRef S);
     47 
     48   /// \brief Get the detected os path suffix for the multi-arch
     49   /// target variant. Always starts with a '/', unless empty
     50   const std::string &osSuffix() const {
     51     assert(OSSuffix.empty() ||
     52            (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1));
     53     return OSSuffix;
     54   }
     55   /// Set the os path suffix.
     56   Multilib &osSuffix(StringRef S);
     57 
     58   /// \brief Get the include directory suffix. Always starts with a '/', unless
     59   /// empty
     60   const std::string &includeSuffix() const {
     61     assert(IncludeSuffix.empty() ||
     62            (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1));
     63     return IncludeSuffix;
     64   }
     65   /// Set the include directory suffix
     66   Multilib &includeSuffix(StringRef S);
     67 
     68   /// \brief Get the flags that indicate or contraindicate this multilib's use
     69   /// All elements begin with either '+' or '-'
     70   const flags_list &flags() const { return Flags; }
     71   flags_list &flags() { return Flags; }
     72   /// Add a flag to the flags list
     73   Multilib &flag(StringRef F) {
     74     assert(F.front() == '+' || F.front() == '-');
     75     Flags.push_back(F);
     76     return *this;
     77   }
     78 
     79   /// \brief print summary of the Multilib
     80   void print(raw_ostream &OS) const;
     81 
     82   /// Check whether any of the 'against' flags contradict the 'for' flags.
     83   bool isValid() const;
     84 
     85   /// Check whether the default is selected
     86   bool isDefault() const
     87   { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); }
     88 
     89   bool operator==(const Multilib &Other) const;
     90 };
     91 
     92 raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
     93 
     94 class MultilibSet {
     95 public:
     96   typedef std::vector<Multilib> multilib_list;
     97   typedef multilib_list::iterator iterator;
     98   typedef multilib_list::const_iterator const_iterator;
     99 
    100   struct FilterCallback {
    101     virtual ~FilterCallback() {};
    102     /// \return true iff the filter should remove the Multilib from the set
    103     virtual bool operator()(const Multilib &M) const = 0;
    104   };
    105 
    106 private:
    107   multilib_list Multilibs;
    108 
    109 public:
    110   MultilibSet() {}
    111 
    112   /// Add an optional Multilib segment
    113   MultilibSet &Maybe(const Multilib &M);
    114 
    115   /// Add a set of mutually incompatible Multilib segments
    116   MultilibSet &Either(const Multilib &M1, const Multilib &M2);
    117   MultilibSet &Either(const Multilib &M1, const Multilib &M2,
    118                       const Multilib &M3);
    119   MultilibSet &Either(const Multilib &M1, const Multilib &M2,
    120                       const Multilib &M3, const Multilib &M4);
    121   MultilibSet &Either(const Multilib &M1, const Multilib &M2,
    122                       const Multilib &M3, const Multilib &M4,
    123                       const Multilib &M5);
    124   MultilibSet &Either(const std::vector<Multilib> &Ms);
    125 
    126   /// Filter out some subset of the Multilibs using a user defined callback
    127   MultilibSet &FilterOut(const FilterCallback &F);
    128   /// Filter out those Multilibs whose gccSuffix matches the given expression
    129   MultilibSet &FilterOut(std::string Regex);
    130 
    131   /// Add a completed Multilib to the set
    132   void push_back(const Multilib &M);
    133 
    134   /// Union this set of multilibs with another
    135   void combineWith(const MultilibSet &MS);
    136 
    137   /// Remove all of thie multilibs from the set
    138   void clear() { Multilibs.clear(); }
    139 
    140   iterator begin() { return Multilibs.begin(); }
    141   const_iterator begin() const { return Multilibs.begin(); }
    142 
    143   iterator end() { return Multilibs.end(); }
    144   const_iterator end() const { return Multilibs.end(); }
    145 
    146   /// Pick the best multilib in the set, \returns false if none are compatible
    147   bool select(const Multilib::flags_list &Flags, Multilib &M) const;
    148 
    149   unsigned size() const { return Multilibs.size(); }
    150 
    151   void print(raw_ostream &OS) const;
    152 
    153 private:
    154   /// Apply the filter to Multilibs and return the subset that remains
    155   static multilib_list filterCopy(const FilterCallback &F,
    156                                   const multilib_list &Ms);
    157 
    158   /// Apply the filter to the multilib_list, removing those that don't match
    159   static void filterInPlace(const FilterCallback &F, multilib_list &Ms);
    160 };
    161 
    162 raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
    163 }
    164 }
    165 
    166 #endif
    167 
    168