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