1 //===- MCLDAttribute.cpp --------------------------------------------------===//
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 #include "mcld/MC/Attribute.h"
10 
11 #include "mcld/MC/AttributeSet.h"
12 #include "mcld/Support/MsgHandling.h"
13 
14 namespace mcld {
15 
16 //===----------------------------------------------------------------------===//
17 // AttrConstraint
18 //===----------------------------------------------------------------------===//
isLegal(const Attribute & pAttr) const19 bool AttrConstraint::isLegal(const Attribute& pAttr) const {
20   if (!isWholeArchive() && pAttr.isWholeArchive()) {
21     error(diag::err_unsupported_whole_archive);
22     return false;
23   }
24   if (!isAsNeeded() && pAttr.isAsNeeded()) {
25     error(diag::err_unsupported_as_needed);
26     return false;
27   }
28   if (!isAddNeeded() && pAttr.isAddNeeded()) {
29     error(diag::err_unsupported_add_needed);
30     return false;
31   }
32   if (isStaticSystem() && pAttr.isDynamic()) {
33     error(diag::err_unsupported_Bdynamic);
34     return false;
35   }
36   if (isStaticSystem() && pAttr.isAsNeeded()) {
37     warning(diag::err_enable_as_needed_on_static_system);
38     return true;
39   }
40   // FIXME: may be it's legal, but ignored by GNU ld.
41   if (pAttr.isAsNeeded() && pAttr.isStatic()) {
42     warning(diag::err_mix_static_as_needed);
43     return true;
44   }
45   return true;
46 }
47 
48 //===----------------------------------------------------------------------===//
49 // AttributeProxy
50 //===----------------------------------------------------------------------===//
AttributeProxy(AttributeSet & pParent,const Attribute & pBase,const AttrConstraint & pConstraint)51 AttributeProxy::AttributeProxy(AttributeSet& pParent,
52                                const Attribute& pBase,
53                                const AttrConstraint& pConstraint)
54     : m_AttrPool(pParent), m_pBase(&pBase), m_Constraint(pConstraint) {
55 }
56 
~AttributeProxy()57 AttributeProxy::~AttributeProxy() {
58 }
59 
isWholeArchive() const60 bool AttributeProxy::isWholeArchive() const {
61   if (m_Constraint.isWholeArchive())
62     return m_pBase->isWholeArchive();
63   else
64     return false;
65 }
66 
isAsNeeded() const67 bool AttributeProxy::isAsNeeded() const {
68   if (m_Constraint.isAsNeeded())
69     return m_pBase->isAsNeeded();
70   else
71     return false;
72 }
73 
isAddNeeded() const74 bool AttributeProxy::isAddNeeded() const {
75   if (m_Constraint.isAddNeeded())
76     return m_pBase->isAddNeeded();
77   else
78     return false;
79 }
80 
isStatic() const81 bool AttributeProxy::isStatic() const {
82   if (m_Constraint.isSharedSystem())
83     return m_pBase->isStatic();
84   else
85     return true;
86 }
87 
isDynamic() const88 bool AttributeProxy::isDynamic() const {
89   if (m_Constraint.isSharedSystem())
90     return m_pBase->isDynamic();
91   else
92     return false;
93 }
94 
ReplaceOrRecord(AttributeSet & pParent,const Attribute * & pBase,Attribute * & pCopy)95 static inline void ReplaceOrRecord(AttributeSet& pParent,
96                                    const Attribute*& pBase,
97                                    Attribute*& pCopy) {
98   Attribute* result = pParent.exists(*pCopy);
99   if (result == NULL) {  // can not find
100     pParent.record(*pCopy);
101     pBase = pCopy;
102   } else {  // find
103     delete pCopy;
104     pBase = result;
105   }
106 }
107 
setWholeArchive()108 void AttributeProxy::setWholeArchive() {
109   Attribute* copy = new Attribute(*m_pBase);
110   copy->setWholeArchive();
111   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
112 }
113 
unsetWholeArchive()114 void AttributeProxy::unsetWholeArchive() {
115   Attribute* copy = new Attribute(*m_pBase);
116   copy->unsetWholeArchive();
117   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
118 }
119 
setAsNeeded()120 void AttributeProxy::setAsNeeded() {
121   Attribute* copy = new Attribute(*m_pBase);
122   copy->setAsNeeded();
123   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
124 }
125 
unsetAsNeeded()126 void AttributeProxy::unsetAsNeeded() {
127   Attribute* copy = new Attribute(*m_pBase);
128   copy->unsetAsNeeded();
129   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
130 }
131 
setAddNeeded()132 void AttributeProxy::setAddNeeded() {
133   Attribute* copy = new Attribute(*m_pBase);
134   copy->setAddNeeded();
135   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
136 }
137 
unsetAddNeeded()138 void AttributeProxy::unsetAddNeeded() {
139   Attribute* copy = new Attribute(*m_pBase);
140   copy->unsetAddNeeded();
141   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
142 }
143 
setStatic()144 void AttributeProxy::setStatic() {
145   Attribute* copy = new Attribute(*m_pBase);
146   copy->setStatic();
147   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
148 }
149 
setDynamic()150 void AttributeProxy::setDynamic() {
151   Attribute* copy = new Attribute(*m_pBase);
152   copy->setDynamic();
153   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
154 }
155 
assign(Attribute * pBase)156 AttributeProxy& AttributeProxy::assign(Attribute* pBase) {
157   m_pBase = pBase;
158   return *this;
159 }
160 
161 }  // namespace mcld
162