1//===- StrSymPool.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
10#include "mcld/LD/StrSymPool.h"
11#include "mcld/LD/Resolver.h"
12#include <llvm/Support/raw_ostream.h>
13
14using namespace mcld;
15
16//==========================
17// StrSymPool
18StrSymPool::StrSymPool(const Resolver& pResolver, StrSymPool::size_type pSize)
19  : m_pResolver(pResolver.clone()), m_Table(pSize) {
20}
21
22StrSymPool::~StrSymPool()
23{
24  if (0 != m_pResolver)
25    delete m_pResolver;
26}
27
28/// createSymbol - create a symbol
29ResolveInfo* StrSymPool::createSymbol(const llvm::StringRef& pName,
30                                      bool pIsDyn,
31                                      ResolveInfo::Type pType,
32                                      ResolveInfo::Desc pDesc,
33                                      ResolveInfo::Binding pBinding,
34                                      ResolveInfo::SizeType pSize,
35                                      ResolveInfo::Visibility pVisibility)
36{
37  ResolveInfo* result = m_Table.getEntryFactory().produce(pName);
38  result->setIsSymbol(true);
39  result->setSource(pIsDyn);
40  result->setType(pType);
41  result->setDesc(pDesc);
42  result->setBinding(pBinding);
43  result->setVisibility(pVisibility);
44  result->setSize(pSize);
45  return result;
46}
47
48/// insertSymbol - insert a symbol and resolve it immediately
49/// @return the pointer of resolved ResolveInfo
50/// @return is the symbol existent?
51void StrSymPool::insertSymbol(const llvm::StringRef& pName,
52                              bool pIsDyn,
53                              ResolveInfo::Type pType,
54                              ResolveInfo::Desc pDesc,
55                              ResolveInfo::Binding pBinding,
56                              ResolveInfo::SizeType pSize,
57                              ResolveInfo::Visibility pVisibility,
58                              ResolveInfo* pOldInfo,
59                              Resolver::Result& pResult)
60{
61  // We should check if there is any symbol with the same name existed.
62  // If it already exists, we should use resolver to decide which symbol
63  // should be reserved. Otherwise, we insert the symbol and set up its
64  // attributes.
65  bool exist = false;
66  ResolveInfo* old_symbol = m_Table.insert(pName, exist);
67  ResolveInfo* new_symbol = NULL;
68  if (exist && old_symbol->isSymbol()) {
69    exist = true;
70    new_symbol = m_Table.getEntryFactory().produce(pName);
71  }
72  else {
73    exist = false;
74    new_symbol = old_symbol;
75  }
76
77  new_symbol->setIsSymbol(true);
78  new_symbol->setSource(pIsDyn);
79  new_symbol->setType(pType);
80  new_symbol->setDesc(pDesc);
81  new_symbol->setBinding(pBinding);
82  new_symbol->setVisibility(pVisibility);
83  new_symbol->setSize(pSize);
84
85  if (!exist) {
86    // not exit or not a symbol
87    pResult.info      = new_symbol;
88    pResult.existent  = false;
89    pResult.overriden = true;
90    return;
91  }
92  else if (NULL != pOldInfo) {
93    // existent, remember its attribute
94    pOldInfo->override(*old_symbol);
95  }
96
97  // exit and is a symbol
98  // symbol resolution
99  bool override = false;
100  unsigned int action = Resolver::LastAction;
101  switch(m_pResolver->resolve(*old_symbol, *new_symbol, override)) {
102    case Resolver::Success: {
103      pResult.info      = old_symbol;
104      pResult.existent  = true;
105      pResult.overriden = override;
106      break;
107    }
108    case Resolver::Warning: {
109      llvm::errs() << "WARNING: " << m_pResolver->mesg() << "\n";
110      m_pResolver->clearMesg();
111      pResult.info      = old_symbol;
112      pResult.existent  = true;
113      pResult.overriden = override;
114      break;
115    }
116    case Resolver::Abort: {
117      llvm::report_fatal_error(m_pResolver->mesg());
118      pResult.info      = old_symbol;
119      pResult.existent  = true;
120      pResult.overriden = override;
121      break;
122    }
123    default: {
124      m_pResolver->resolveAgain(*this, action, *old_symbol, *new_symbol, pResult);
125      break;
126    }
127  }
128  return;
129}
130
131llvm::StringRef StrSymPool::insertString(const llvm::StringRef& pString)
132{
133  bool exist = false;
134  ResolveInfo* resolve_info = m_Table.insert(pString, exist);
135  return llvm::StringRef(resolve_info->name(), resolve_info->nameSize());
136}
137
138void StrSymPool::reserve(StrSymPool::size_type pSize)
139{
140  m_Table.rehash(pSize);
141}
142
143StrSymPool::size_type StrSymPool::capacity() const
144{
145  return (m_Table.numOfBuckets() - m_Table.numOfEntries());
146}
147
148/// findInfo - find the resolved ResolveInfo
149ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName)
150{
151  Table::iterator iter = m_Table.find(pName);
152  return iter.getEntry();
153}
154
155/// findInfo - find the resolved ResolveInfo
156const ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName) const
157{
158  Table::const_iterator iter = m_Table.find(pName);
159  return iter.getEntry();
160}
161
162/// findSymbol - find the resolved output LDSymbol
163LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName)
164{
165  ResolveInfo* info = findInfo(pName);
166  if (NULL == info)
167    return NULL;
168  return info->outSymbol();
169}
170
171/// findSymbol - find the resolved output LDSymbol
172const LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName) const
173{
174  const ResolveInfo* info = findInfo(pName);
175  if (NULL == info)
176    return NULL;
177  return info->outSymbol();
178}
179
180