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