//===- ResolveInfo.cpp ----------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "mcld/LD/ResolveInfo.h"
#include "mcld/LinkerConfig.h"
#include "mcld/LD/LDSection.h"
#include "mcld/Support/GCFactory.h"
#include <llvm/Support/ManagedStatic.h>
#include <cstdlib>
#include <cstring>
namespace mcld {
/// g_NullResolveInfo - a pointer to Null ResolveInfo.
static ResolveInfo* g_NullResolveInfo = NULL;
//===----------------------------------------------------------------------===//
// ResolveInfo
//===----------------------------------------------------------------------===//
ResolveInfo::ResolveInfo() : m_Size(0), m_BitField(0) {
m_Ptr.sym_ptr = 0;
}
ResolveInfo::~ResolveInfo() {
}
void ResolveInfo::override(const ResolveInfo& pFrom) {
m_Size = pFrom.m_Size;
overrideAttributes(pFrom);
overrideVisibility(pFrom);
}
void ResolveInfo::overrideAttributes(const ResolveInfo& pFrom) {
m_BitField &= ~RESOLVE_MASK | VISIBILITY_MASK;
m_BitField |= (pFrom.m_BitField & (RESOLVE_MASK & ~VISIBILITY_MASK));
}
/// overrideVisibility - override the visibility
/// always use the most strict visibility
void ResolveInfo::overrideVisibility(const ResolveInfo& pFrom) {
// The rule for combining visibility is that we always choose the
// most constrained visibility. In order of increasing constraint,
// visibility goes PROTECTED, HIDDEN, INTERNAL. This is the reverse
// of the numeric values, so the effect is that we always want the
// smallest non-zero value.
//
// enum {
// STV_DEFAULT = 0,
// STV_INTERNAL = 1,
// STV_HIDDEN = 2,
// STV_PROTECTED = 3
// };
Visibility from_vis = pFrom.visibility();
Visibility cur_vis = visibility();
if (from_vis != 0) {
if (cur_vis == 0)
setVisibility(from_vis);
else if (cur_vis > from_vis)
setVisibility(from_vis);
}
}
void ResolveInfo::setRegular() {
m_BitField &= (~dynamic_flag);
}
void ResolveInfo::setDynamic() {
m_BitField |= dynamic_flag;
}
void ResolveInfo::setSource(bool pIsDyn) {
if (pIsDyn)
m_BitField |= dynamic_flag;
else
m_BitField &= (~dynamic_flag);
}
void ResolveInfo::setInDyn() {
m_BitField |= indyn_flag;
}
void ResolveInfo::setType(uint32_t pType) {
m_BitField &= ~TYPE_MASK;
m_BitField |= ((pType << TYPE_OFFSET) & TYPE_MASK);
}
void ResolveInfo::setDesc(uint32_t pDesc) {
m_BitField &= ~DESC_MASK;
m_BitField |= ((pDesc << DESC_OFFSET) & DESC_MASK);
}
void ResolveInfo::setBinding(uint32_t pBinding) {
m_BitField &= ~BINDING_MASK;
if (pBinding == Local || pBinding == Absolute)
m_BitField |= local_flag;
if (pBinding == Weak || pBinding == Absolute)
m_BitField |= weak_flag;
}
void ResolveInfo::setReserved(uint32_t pReserved) {
m_BitField &= ~RESERVED_MASK;
m_BitField |= ((pReserved << RESERVED_OFFSET) & RESERVED_MASK);
}
void ResolveInfo::setOther(uint32_t pOther) {
setVisibility(static_cast<ResolveInfo::Visibility>(pOther & 0x3));
}
void ResolveInfo::setVisibility(ResolveInfo::Visibility pVisibility) {
m_BitField &= ~VISIBILITY_MASK;
m_BitField |= pVisibility << VISIBILITY_OFFSET;
}
void ResolveInfo::setIsSymbol(bool pIsSymbol) {
if (pIsSymbol)
m_BitField |= symbol_flag;
else
m_BitField &= ~symbol_flag;
}
bool ResolveInfo::isNull() const {
return (this == Null());
}
bool ResolveInfo::isDyn() const {
return (dynamic_flag == (m_BitField & DYN_MASK));
}
bool ResolveInfo::isUndef() const {
return (undefine_flag == (m_BitField & DESC_MASK));
}
bool ResolveInfo::isDefine() const {
return (define_flag == (m_BitField & DESC_MASK));
}
bool ResolveInfo::isCommon() const {
return (common_flag == (m_BitField & DESC_MASK));
}
bool ResolveInfo::isIndirect() const {
return (indirect_flag == (m_BitField & DESC_MASK));
}
// isGlobal - [L,W] == [0, 0]
bool ResolveInfo::isGlobal() const {
return (global_flag == (m_BitField & BINDING_MASK));
}
// isWeak - [L,W] == [0, 1]
bool ResolveInfo::isWeak() const {
return (weak_flag == (m_BitField & BINDING_MASK));
}
// isLocal - [L,W] == [1, 0]
bool ResolveInfo::isLocal() const {
return (local_flag == (m_BitField & BINDING_MASK));
}
// isAbsolute - [L,W] == [1, 1]
bool ResolveInfo::isAbsolute() const {
return (absolute_flag == (m_BitField & BINDING_MASK));
}
bool ResolveInfo::isSymbol() const {
return (symbol_flag == (m_BitField & SYMBOL_MASK));
}
bool ResolveInfo::isString() const {
return (string_flag == (m_BitField & SYMBOL_MASK));
}
bool ResolveInfo::isInDyn() const {
return (indyn_flag == (m_BitField & IN_DYN_MASK));
}
uint32_t ResolveInfo::type() const {
return (m_BitField & TYPE_MASK) >> TYPE_OFFSET;
}
uint32_t ResolveInfo::desc() const {
return (m_BitField & DESC_MASK) >> DESC_OFFSET;
}
uint32_t ResolveInfo::binding() const {
if (m_BitField & LOCAL_MASK) {
if (m_BitField & GLOBAL_MASK) {
return ResolveInfo::Absolute;
}
return ResolveInfo::Local;
}
return m_BitField & GLOBAL_MASK;
}
uint32_t ResolveInfo::reserved() const {
return (m_BitField & RESERVED_MASK) >> RESERVED_OFFSET;
}
ResolveInfo::Visibility ResolveInfo::visibility() const {
return static_cast<ResolveInfo::Visibility>((m_BitField & VISIBILITY_MASK) >>
VISIBILITY_OFFSET);
}
bool ResolveInfo::compare(const ResolveInfo::key_type& pKey) {
size_t length = nameSize();
if (length != pKey.size())
return false;
return (std::memcmp(m_Name, pKey.data(), length) == 0);
}
bool ResolveInfo::shouldForceLocal(const LinkerConfig& pConfig) {
// forced local symbol matches all rules:
// 1. We are not doing incremental linking.
// 2. The symbol is with Hidden or Internal visibility.
// 3. The symbol should be global or weak. Otherwise, local symbol is local.
// 4. The symbol is defined or common
if (LinkerConfig::Object != pConfig.codeGenType() &&
(visibility() == ResolveInfo::Hidden ||
visibility() == ResolveInfo::Internal) &&
(isGlobal() || isWeak()) && (isDefine() || isCommon()))
return true;
return false;
}
//===----------------------------------------------------------------------===//
// ResolveInfo Factory Methods
//===----------------------------------------------------------------------===//
ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey) {
ResolveInfo* info =
static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + pKey.size() + 1));
if (info == NULL)
return NULL;
new (info) ResolveInfo(); // call constructor at the `result` address.
std::memcpy(info->m_Name, pKey.data(), pKey.size());
info->m_Name[pKey.size()] = '\0';
info->m_BitField &= ~ResolveInfo::RESOLVE_MASK;
info->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET);
return info;
}
void ResolveInfo::Destroy(ResolveInfo*& pInfo) {
if (pInfo->isNull())
return;
if (pInfo != NULL) {
pInfo->~ResolveInfo();
free(pInfo);
}
pInfo = NULL;
}
ResolveInfo* ResolveInfo::Null() {
if (g_NullResolveInfo == NULL) {
g_NullResolveInfo =
static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + 1));
new (g_NullResolveInfo) ResolveInfo();
g_NullResolveInfo->m_Name[0] = '\0';
g_NullResolveInfo->m_BitField = 0x0;
g_NullResolveInfo->setBinding(Local);
}
return g_NullResolveInfo;
}
} // namespace mcld