1//===- ResolveInfo.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/LD/ResolveInfo.h"
10
11#include "mcld/LinkerConfig.h"
12#include "mcld/LD/LDSection.h"
13#include "mcld/Support/GCFactory.h"
14
15#include <llvm/Support/ManagedStatic.h>
16
17#include <cstdlib>
18#include <cstring>
19
20namespace mcld {
21
22/// g_NullResolveInfo - a pointer to Null ResolveInfo.
23static ResolveInfo* g_NullResolveInfo = NULL;
24
25//===----------------------------------------------------------------------===//
26// ResolveInfo
27//===----------------------------------------------------------------------===//
28ResolveInfo::ResolveInfo() : m_Size(0), m_BitField(0) {
29  m_Ptr.sym_ptr = 0;
30}
31
32ResolveInfo::~ResolveInfo() {
33}
34
35void ResolveInfo::override(const ResolveInfo& pFrom) {
36  m_Size = pFrom.m_Size;
37  overrideAttributes(pFrom);
38  overrideVisibility(pFrom);
39}
40
41void ResolveInfo::overrideAttributes(const ResolveInfo& pFrom) {
42  m_BitField &= ~RESOLVE_MASK | VISIBILITY_MASK;
43  m_BitField |= (pFrom.m_BitField & (RESOLVE_MASK & ~VISIBILITY_MASK));
44}
45
46/// overrideVisibility - override the visibility
47///   always use the most strict visibility
48void ResolveInfo::overrideVisibility(const ResolveInfo& pFrom) {
49  // The rule for combining visibility is that we always choose the
50  // most constrained visibility.  In order of increasing constraint,
51  // visibility goes PROTECTED, HIDDEN, INTERNAL.  This is the reverse
52  // of the numeric values, so the effect is that we always want the
53  // smallest non-zero value.
54  //
55  // enum {
56  //   STV_DEFAULT = 0,
57  //   STV_INTERNAL = 1,
58  //   STV_HIDDEN = 2,
59  //   STV_PROTECTED = 3
60  // };
61
62  Visibility from_vis = pFrom.visibility();
63  Visibility cur_vis = visibility();
64  if (from_vis != 0) {
65    if (cur_vis == 0)
66      setVisibility(from_vis);
67    else if (cur_vis > from_vis)
68      setVisibility(from_vis);
69  }
70}
71
72void ResolveInfo::setRegular() {
73  m_BitField &= (~dynamic_flag);
74}
75
76void ResolveInfo::setDynamic() {
77  m_BitField |= dynamic_flag;
78}
79
80void ResolveInfo::setSource(bool pIsDyn) {
81  if (pIsDyn)
82    m_BitField |= dynamic_flag;
83  else
84    m_BitField &= (~dynamic_flag);
85}
86
87void ResolveInfo::setInDyn() {
88  m_BitField |= indyn_flag;
89}
90
91void ResolveInfo::setType(uint32_t pType) {
92  m_BitField &= ~TYPE_MASK;
93  m_BitField |= ((pType << TYPE_OFFSET) & TYPE_MASK);
94}
95
96void ResolveInfo::setDesc(uint32_t pDesc) {
97  m_BitField &= ~DESC_MASK;
98  m_BitField |= ((pDesc << DESC_OFFSET) & DESC_MASK);
99}
100
101void ResolveInfo::setBinding(uint32_t pBinding) {
102  m_BitField &= ~BINDING_MASK;
103  if (pBinding == Local || pBinding == Absolute)
104    m_BitField |= local_flag;
105  if (pBinding == Weak || pBinding == Absolute)
106    m_BitField |= weak_flag;
107}
108
109void ResolveInfo::setReserved(uint32_t pReserved) {
110  m_BitField &= ~RESERVED_MASK;
111  m_BitField |= ((pReserved << RESERVED_OFFSET) & RESERVED_MASK);
112}
113
114void ResolveInfo::setOther(uint32_t pOther) {
115  setVisibility(static_cast<ResolveInfo::Visibility>(pOther & 0x3));
116}
117
118void ResolveInfo::setVisibility(ResolveInfo::Visibility pVisibility) {
119  m_BitField &= ~VISIBILITY_MASK;
120  m_BitField |= pVisibility << VISIBILITY_OFFSET;
121}
122
123void ResolveInfo::setIsSymbol(bool pIsSymbol) {
124  if (pIsSymbol)
125    m_BitField |= symbol_flag;
126  else
127    m_BitField &= ~symbol_flag;
128}
129
130bool ResolveInfo::isNull() const {
131  return (this == Null());
132}
133
134bool ResolveInfo::isDyn() const {
135  return (dynamic_flag == (m_BitField & DYN_MASK));
136}
137
138bool ResolveInfo::isUndef() const {
139  return (undefine_flag == (m_BitField & DESC_MASK));
140}
141
142bool ResolveInfo::isDefine() const {
143  return (define_flag == (m_BitField & DESC_MASK));
144}
145
146bool ResolveInfo::isCommon() const {
147  return (common_flag == (m_BitField & DESC_MASK));
148}
149
150bool ResolveInfo::isIndirect() const {
151  return (indirect_flag == (m_BitField & DESC_MASK));
152}
153
154// isGlobal - [L,W] == [0, 0]
155bool ResolveInfo::isGlobal() const {
156  return (global_flag == (m_BitField & BINDING_MASK));
157}
158
159// isWeak - [L,W] == [0, 1]
160bool ResolveInfo::isWeak() const {
161  return (weak_flag == (m_BitField & BINDING_MASK));
162}
163
164// isLocal - [L,W] == [1, 0]
165bool ResolveInfo::isLocal() const {
166  return (local_flag == (m_BitField & BINDING_MASK));
167}
168
169// isAbsolute - [L,W] == [1, 1]
170bool ResolveInfo::isAbsolute() const {
171  return (absolute_flag == (m_BitField & BINDING_MASK));
172}
173
174bool ResolveInfo::isSymbol() const {
175  return (symbol_flag == (m_BitField & SYMBOL_MASK));
176}
177
178bool ResolveInfo::isString() const {
179  return (string_flag == (m_BitField & SYMBOL_MASK));
180}
181
182bool ResolveInfo::isInDyn() const {
183  return (indyn_flag == (m_BitField & IN_DYN_MASK));
184}
185
186uint32_t ResolveInfo::type() const {
187  return (m_BitField & TYPE_MASK) >> TYPE_OFFSET;
188}
189
190uint32_t ResolveInfo::desc() const {
191  return (m_BitField & DESC_MASK) >> DESC_OFFSET;
192}
193
194uint32_t ResolveInfo::binding() const {
195  if (m_BitField & LOCAL_MASK) {
196    if (m_BitField & GLOBAL_MASK) {
197      return ResolveInfo::Absolute;
198    }
199    return ResolveInfo::Local;
200  }
201  return m_BitField & GLOBAL_MASK;
202}
203
204uint32_t ResolveInfo::reserved() const {
205  return (m_BitField & RESERVED_MASK) >> RESERVED_OFFSET;
206}
207
208ResolveInfo::Visibility ResolveInfo::visibility() const {
209  return static_cast<ResolveInfo::Visibility>((m_BitField & VISIBILITY_MASK) >>
210                                              VISIBILITY_OFFSET);
211}
212
213bool ResolveInfo::compare(const ResolveInfo::key_type& pKey) {
214  size_t length = nameSize();
215  if (length != pKey.size())
216    return false;
217  return (std::memcmp(m_Name, pKey.data(), length) == 0);
218}
219
220bool ResolveInfo::shouldForceLocal(const LinkerConfig& pConfig) {
221  // forced local symbol matches all rules:
222  // 1. We are not doing incremental linking.
223  // 2. The symbol is with Hidden or Internal visibility.
224  // 3. The symbol should be global or weak. Otherwise, local symbol is local.
225  // 4. The symbol is defined or common
226  if (LinkerConfig::Object != pConfig.codeGenType() &&
227      (visibility() == ResolveInfo::Hidden ||
228       visibility() == ResolveInfo::Internal) &&
229      (isGlobal() || isWeak()) && (isDefine() || isCommon()))
230    return true;
231  return false;
232}
233//===----------------------------------------------------------------------===//
234// ResolveInfo Factory Methods
235//===----------------------------------------------------------------------===//
236ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey) {
237  ResolveInfo* info =
238      static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + pKey.size() + 1));
239  if (info == NULL)
240    return NULL;
241
242  new (info) ResolveInfo();  // call constructor at the `result` address.
243  std::memcpy(info->m_Name, pKey.data(), pKey.size());
244  info->m_Name[pKey.size()] = '\0';
245  info->m_BitField &= ~ResolveInfo::RESOLVE_MASK;
246  info->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET);
247  return info;
248}
249
250void ResolveInfo::Destroy(ResolveInfo*& pInfo) {
251  if (pInfo->isNull())
252    return;
253
254  if (pInfo != NULL) {
255    pInfo->~ResolveInfo();
256    free(pInfo);
257  }
258
259  pInfo = NULL;
260}
261
262ResolveInfo* ResolveInfo::Null() {
263  if (g_NullResolveInfo == NULL) {
264    g_NullResolveInfo =
265        static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + 1));
266    new (g_NullResolveInfo) ResolveInfo();
267    g_NullResolveInfo->m_Name[0] = '\0';
268    g_NullResolveInfo->m_BitField = 0x0;
269    g_NullResolveInfo->setBinding(Local);
270  }
271  return g_NullResolveInfo;
272}
273
274}  // namespace mcld
275