Home | History | Annotate | Download | only in MC
      1 //===- MCLDAttribute.h ----------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #ifndef MCLD_ATTRIBUTE_H
     10 #define MCLD_ATTRIBUTE_H
     11 #ifdef ENABLE_UNITTEST
     12 #include <gtest.h>
     13 #endif
     14 #include <vector>
     15 #include <string>
     16 
     17 namespace mcld
     18 {
     19 class AttributeFactory;
     20 
     21 /** \class AttributeBase
     22  *  \brief AttributeBase provides the real storage for attributes of options.
     23  *
     24  *  Attributes are options affecting the link editing of input files.
     25  *  Some options affects the input files mentioned on the command line after
     26  *  them. For example, --whole-archive option affects archives mentioned on
     27  *  the command line after the --whole-archve option. We call such options
     28  *  "attributes of input files"
     29  *
     30  *  AttributeBase is the storage for attributes of input files. Each input
     31  *  file (@see mcld::Input in MCLinker) has a pointer of an attribute. Since
     32  *  most attributes of input files are identical, our design lets input files
     33  *  which have identical attributes share common attribute. AttributeBase is
     34  *  the shared storage for attribute.
     35  */
     36 class AttributeBase
     37 {
     38 public:
     39   AttributeBase()
     40   : m_WholeArchive(false),
     41     m_AsNeeded(false),
     42     m_AddNeeded(true),
     43     m_Static(false)
     44   { }
     45 
     46   AttributeBase(const AttributeBase& pBase)
     47   : m_WholeArchive(pBase.m_WholeArchive),
     48     m_AsNeeded(pBase.m_AsNeeded),
     49     m_AddNeeded(pBase.m_AddNeeded),
     50     m_Static(pBase.m_Static)
     51   { }
     52 
     53   virtual ~AttributeBase()
     54   { }
     55 
     56   // ----- observers  ----- //
     57   // represent GNU ld --whole-archive/--no-whole-archive options
     58   bool isWholeArchive() const
     59   { return m_WholeArchive; }
     60 
     61   // represent GNU ld --as-needed/--no-as-needed options
     62   bool isAsNeeded() const
     63   { return m_AsNeeded; }
     64 
     65   // represent GNU ld --add-needed/--no-add-needed options
     66   bool isAddNeeded() const
     67   { return m_AddNeeded; }
     68 
     69   // represent GNU ld -static option
     70   bool isStatic() const
     71   { return m_Static; }
     72 
     73   // represent GNU ld -call_shared option
     74   bool isDynamic() const
     75   { return !m_Static; }
     76 public:
     77   bool m_WholeArchive : 1;
     78   bool m_AsNeeded : 1;
     79   bool m_AddNeeded : 1;
     80   bool m_Static : 1;
     81 };
     82 
     83 /** \class Attribute
     84  *  \brief The base class of attributes. Providing the raw operations of an
     85  *  attributes
     86  *
     87  *  For conventience and producing less bugs, we move the stoarges of attributes
     88  *  onto AttributeBase, and modifiers remains with the class Attribute.
     89  */
     90 class Attribute : public AttributeBase
     91 {
     92 public:
     93   // -----  modifiers  ----- //
     94   void setWholeArchive()
     95   { m_WholeArchive = true; }
     96 
     97   void unsetWholeArchive()
     98   { m_WholeArchive = false; }
     99 
    100   void setAsNeeded()
    101   { m_AsNeeded = true; }
    102 
    103   void unsetAsNeeded()
    104   { m_AsNeeded = false; }
    105 
    106   void setAddNeeded()
    107   { m_AddNeeded = true; }
    108 
    109   void unsetAddNeeded()
    110   { m_AddNeeded = false; }
    111 
    112   void setStatic()
    113   { m_Static = true; }
    114 
    115   void setDynamic()
    116   { m_Static = false; }
    117 };
    118 
    119 /** \class AttrConstraint
    120  *  \brief AttrConstarint is the constraint of a system.
    121  *
    122  *  Some systems can not enable certain attributes of a input file.
    123  *  For example, systems which have no shared libraries can not enable
    124  *  --call_shared options. We call the ability of enabling attributes
    125  *  as the constraint of attributes of a system.
    126  *
    127  *  Systems enable attributes at the target implementation of SectLinker.
    128  *
    129  *  @see SectLinker
    130  */
    131 class AttrConstraint : public AttributeBase
    132 {
    133 public:
    134   void enableWholeArchive()
    135   { m_WholeArchive = true; }
    136 
    137   void disableWholeArchive()
    138   { m_WholeArchive = false; }
    139 
    140   void enableAsNeeded()
    141   { m_AsNeeded = true; }
    142 
    143   void disableAsNeeded()
    144   { m_AsNeeded = false; }
    145 
    146   void enableAddNeeded()
    147   { m_AddNeeded = true; }
    148 
    149   void disableAddNeeded()
    150   { m_AddNeeded = false; }
    151 
    152   void setSharedSystem()
    153   { m_Static = false; }
    154 
    155   void setStaticSystem()
    156   { m_Static = true; }
    157 
    158   bool isSharedSystem() const
    159   { return !m_Static; }
    160 
    161   bool isStaticSystem() const
    162   { return m_Static; }
    163 
    164   bool isLegal(const Attribute& pAttr, std::string& pErrMesg) const;
    165 };
    166 
    167 /** \class AttributeProxy
    168  *  \brief AttributeProxys is the illusion of private attribute of each
    169  *  input file.
    170  *
    171  *  We designers want to hide the details of sharing common attributes
    172  *  between input files. We want input files under the illusion that they
    173  *  have their own private attributes to simplify the linking algorithms.
    174  *
    175  *  AttributeProxy hides the reality of sharing. An input file can change
    176  *  its attribute without explicit searching of existing attributes
    177  *  as it has a private ownership of the attribute. AttributeProxy does
    178  *  the searching in the AttributeFactory and changes the pointer of
    179  *  the attribute of the input file. If the searching fails, AttributeProxy
    180  *  requests a new attribute from the AttributeFactory.
    181  */
    182 class AttributeProxy
    183 {
    184 private:
    185   friend class AttributeFactory;
    186 
    187   explicit AttributeProxy(AttributeFactory& pParent, Attribute& pBase);
    188   ~AttributeProxy();
    189 
    190 public:
    191   // ----- observers  ----- //
    192   bool isWholeArchive() const;
    193 
    194   bool isAsNeeded() const;
    195 
    196   bool isAddNeeded() const;
    197 
    198   bool isStatic() const;
    199 
    200   bool isDynamic() const;
    201 
    202   Attribute* attr()
    203   { return m_pBase; }
    204 
    205   const Attribute* attr() const
    206   { return m_pBase; }
    207 
    208   // -----  modifiers  ----- //
    209   void setWholeArchive();
    210   void unsetWholeArchive();
    211   void setAsNeeded();
    212   void unsetAsNeeded();
    213   void setAddNeeded();
    214   void unsetAddNeeded();
    215   void setStatic();
    216   void setDynamic();
    217 
    218 private:
    219   AttributeProxy* clone() const;
    220 
    221   void change(Attribute* pBase)
    222   { m_pBase = pBase; }
    223 
    224 private:
    225   AttributeFactory &m_AttrPool;
    226   Attribute *m_pBase;
    227 };
    228 
    229 
    230 // -----  comparisons  ----- //
    231 inline bool operator== (const Attribute& pLHS, const Attribute& pRHS)
    232 {
    233   return ((pLHS.isWholeArchive() == pRHS.isWholeArchive()) &&
    234     (pLHS.isAsNeeded() == pRHS.isAsNeeded()) &&
    235     (pLHS.isAddNeeded() == pRHS.isAddNeeded()) &&
    236     (pLHS.isStatic() == pRHS.isStatic()));
    237 }
    238 
    239 inline bool operator!= (const Attribute& pLHS, const Attribute& pRHS)
    240 {
    241   return !(pLHS == pRHS);
    242 }
    243 
    244 } // namespace of mcld
    245 
    246 #endif
    247 
    248