| //===- StrSymPool.cpp -----------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "mcld/LD/StrSymPool.h" |
| #include "mcld/LD/Resolver.h" |
| #include <llvm/Support/raw_ostream.h> |
| |
| using namespace mcld; |
| |
| //========================== |
| // StrSymPool |
| StrSymPool::StrSymPool(const Resolver& pResolver, StrSymPool::size_type pSize) |
| : m_pResolver(pResolver.clone()), m_Table(pSize) { |
| } |
| |
| StrSymPool::~StrSymPool() |
| { |
| if (0 != m_pResolver) |
| delete m_pResolver; |
| } |
| |
| /// createSymbol - create a symbol |
| ResolveInfo* StrSymPool::createSymbol(const llvm::StringRef& pName, |
| bool pIsDyn, |
| ResolveInfo::Type pType, |
| ResolveInfo::Desc pDesc, |
| ResolveInfo::Binding pBinding, |
| ResolveInfo::SizeType pSize, |
| ResolveInfo::Visibility pVisibility) |
| { |
| ResolveInfo* result = m_Table.getEntryFactory().produce(pName); |
| result->setIsSymbol(true); |
| result->setSource(pIsDyn); |
| result->setType(pType); |
| result->setDesc(pDesc); |
| result->setBinding(pBinding); |
| result->setVisibility(pVisibility); |
| result->setSize(pSize); |
| return result; |
| } |
| |
| /// insertSymbol - insert a symbol and resolve it immediately |
| /// @return the pointer of resolved ResolveInfo |
| /// @return is the symbol existent? |
| void StrSymPool::insertSymbol(const llvm::StringRef& pName, |
| bool pIsDyn, |
| ResolveInfo::Type pType, |
| ResolveInfo::Desc pDesc, |
| ResolveInfo::Binding pBinding, |
| ResolveInfo::SizeType pSize, |
| ResolveInfo::Visibility pVisibility, |
| ResolveInfo* pOldInfo, |
| Resolver::Result& pResult) |
| { |
| // We should check if there is any symbol with the same name existed. |
| // If it already exists, we should use resolver to decide which symbol |
| // should be reserved. Otherwise, we insert the symbol and set up its |
| // attributes. |
| bool exist = false; |
| ResolveInfo* old_symbol = m_Table.insert(pName, exist); |
| ResolveInfo* new_symbol = NULL; |
| if (exist && old_symbol->isSymbol()) { |
| exist = true; |
| new_symbol = m_Table.getEntryFactory().produce(pName); |
| } |
| else { |
| exist = false; |
| new_symbol = old_symbol; |
| } |
| |
| new_symbol->setIsSymbol(true); |
| new_symbol->setSource(pIsDyn); |
| new_symbol->setType(pType); |
| new_symbol->setDesc(pDesc); |
| new_symbol->setBinding(pBinding); |
| new_symbol->setVisibility(pVisibility); |
| new_symbol->setSize(pSize); |
| |
| if (!exist) { |
| // not exit or not a symbol |
| pResult.info = new_symbol; |
| pResult.existent = false; |
| pResult.overriden = true; |
| return; |
| } |
| else if (NULL != pOldInfo) { |
| // existent, remember its attribute |
| pOldInfo->override(*old_symbol); |
| } |
| |
| // exit and is a symbol |
| // symbol resolution |
| bool override = false; |
| unsigned int action = Resolver::LastAction; |
| switch(m_pResolver->resolve(*old_symbol, *new_symbol, override)) { |
| case Resolver::Success: { |
| pResult.info = old_symbol; |
| pResult.existent = true; |
| pResult.overriden = override; |
| break; |
| } |
| case Resolver::Warning: { |
| llvm::errs() << "WARNING: " << m_pResolver->mesg() << "\n"; |
| m_pResolver->clearMesg(); |
| pResult.info = old_symbol; |
| pResult.existent = true; |
| pResult.overriden = override; |
| break; |
| } |
| case Resolver::Abort: { |
| llvm::report_fatal_error(m_pResolver->mesg()); |
| pResult.info = old_symbol; |
| pResult.existent = true; |
| pResult.overriden = override; |
| break; |
| } |
| default: { |
| m_pResolver->resolveAgain(*this, action, *old_symbol, *new_symbol, pResult); |
| break; |
| } |
| } |
| return; |
| } |
| |
| llvm::StringRef StrSymPool::insertString(const llvm::StringRef& pString) |
| { |
| bool exist = false; |
| ResolveInfo* resolve_info = m_Table.insert(pString, exist); |
| return llvm::StringRef(resolve_info->name(), resolve_info->nameSize()); |
| } |
| |
| void StrSymPool::reserve(StrSymPool::size_type pSize) |
| { |
| m_Table.rehash(pSize); |
| } |
| |
| StrSymPool::size_type StrSymPool::capacity() const |
| { |
| return (m_Table.numOfBuckets() - m_Table.numOfEntries()); |
| } |
| |
| /// findInfo - find the resolved ResolveInfo |
| ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName) |
| { |
| Table::iterator iter = m_Table.find(pName); |
| return iter.getEntry(); |
| } |
| |
| /// findInfo - find the resolved ResolveInfo |
| const ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName) const |
| { |
| Table::const_iterator iter = m_Table.find(pName); |
| return iter.getEntry(); |
| } |
| |
| /// findSymbol - find the resolved output LDSymbol |
| LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName) |
| { |
| ResolveInfo* info = findInfo(pName); |
| if (NULL == info) |
| return NULL; |
| return info->outSymbol(); |
| } |
| |
| /// findSymbol - find the resolved output LDSymbol |
| const LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName) const |
| { |
| const ResolveInfo* info = findInfo(pName); |
| if (NULL == info) |
| return NULL; |
| return info->outSymbol(); |
| } |
| |