//===- IRBuilder.cpp ------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "mcld/IRBuilder.h"
#include "mcld/Fragment/FragmentRef.h"
#include "mcld/LinkerScript.h"
#include "mcld/LD/DebugString.h"
#include "mcld/LD/EhFrame.h"
#include "mcld/LD/ELFReader.h"
#include "mcld/LD/LDContext.h"
#include "mcld/LD/RelocData.h"
#include "mcld/LD/SectionData.h"
#include "mcld/Object/ObjectBuilder.h"
#include "mcld/Support/ELF.h"
#include "mcld/Support/MemoryArea.h"
#include "mcld/Support/MsgHandling.h"
#include <llvm/ADT/StringRef.h>
namespace mcld {
//===----------------------------------------------------------------------===//
// Helper Functions
//===----------------------------------------------------------------------===//
LDFileFormat::Kind GetELFSectionKind(uint32_t pType,
const char* pName,
uint32_t pFlag) {
if (pFlag & llvm::ELF::SHF_EXCLUDE)
return LDFileFormat::Exclude;
if (pFlag & llvm::ELF::SHF_MASKPROC)
return LDFileFormat::Target;
// name rules
llvm::StringRef name(pName);
if (name.startswith(".debug") || name.startswith(".zdebug") ||
name.startswith(".line") || name.startswith(".stab")) {
if (name.startswith(".debug_str"))
return LDFileFormat::DebugString;
return LDFileFormat::Debug;
}
if (name.startswith(".comment"))
return LDFileFormat::MetaData;
if (name.startswith(".interp") || name.startswith(".dynamic"))
return LDFileFormat::Note;
if (name.startswith(".eh_frame"))
return LDFileFormat::EhFrame;
if (name.startswith(".eh_frame_hdr"))
return LDFileFormat::EhFrameHdr;
if (name.startswith(".gcc_except_table"))
return LDFileFormat::GCCExceptTable;
if (name.startswith(".note.GNU-stack"))
return LDFileFormat::StackNote;
if (name.startswith(".gnu.linkonce"))
return LDFileFormat::LinkOnce;
// type rules
switch (pType) {
case llvm::ELF::SHT_NULL:
return LDFileFormat::Null;
case llvm::ELF::SHT_INIT_ARRAY:
case llvm::ELF::SHT_FINI_ARRAY:
case llvm::ELF::SHT_PREINIT_ARRAY:
case llvm::ELF::SHT_PROGBITS: {
if ((pFlag & llvm::ELF::SHF_EXECINSTR) != 0)
return LDFileFormat::TEXT;
else
return LDFileFormat::DATA;
}
case llvm::ELF::SHT_SYMTAB:
case llvm::ELF::SHT_DYNSYM:
case llvm::ELF::SHT_STRTAB:
case llvm::ELF::SHT_HASH:
case llvm::ELF::SHT_DYNAMIC:
case llvm::ELF::SHT_SYMTAB_SHNDX:
return LDFileFormat::NamePool;
case llvm::ELF::SHT_RELA:
case llvm::ELF::SHT_REL:
return LDFileFormat::Relocation;
case llvm::ELF::SHT_NOBITS:
return LDFileFormat::BSS;
case llvm::ELF::SHT_NOTE:
return LDFileFormat::Note;
case llvm::ELF::SHT_GROUP:
return LDFileFormat::Group;
case llvm::ELF::SHT_GNU_versym:
case llvm::ELF::SHT_GNU_verdef:
case llvm::ELF::SHT_GNU_verneed:
return LDFileFormat::Version;
case llvm::ELF::SHT_SHLIB:
return LDFileFormat::Target;
default:
if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) ||
(pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
(pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
return LDFileFormat::Target;
fatal(diag::err_unsupported_section) << pName << pType;
}
return LDFileFormat::MetaData;
}
//===----------------------------------------------------------------------===//
// IRBuilder
//===----------------------------------------------------------------------===//
IRBuilder::IRBuilder(Module& pModule, const LinkerConfig& pConfig)
: m_Module(pModule), m_Config(pConfig), m_InputBuilder(pConfig) {
m_InputBuilder.setCurrentTree(m_Module.getInputTree());
// FIXME: where to set up Relocation?
Relocation::SetUp(m_Config);
}
IRBuilder::~IRBuilder() {
}
/// CreateInput - To create an input file and append it to the input tree.
Input* IRBuilder::CreateInput(const std::string& pName,
const sys::fs::Path& pPath,
Input::Type pType) {
if (Input::Unknown == pType)
return ReadInput(pName, pPath);
m_InputBuilder.createNode<InputTree::Positional>(pName, pPath, pType);
Input* input = *m_InputBuilder.getCurrentNode();
if (!input->hasContext())
m_InputBuilder.setContext(*input, false);
return input;
}
/// ReadInput - To read an input file and append it to the input tree.
Input* IRBuilder::ReadInput(const std::string& pName,
const sys::fs::Path& pPath) {
m_InputBuilder.createNode<InputTree::Positional>(
pName, pPath, Input::Unknown);
Input* input = *m_InputBuilder.getCurrentNode();
if (!input->hasContext())
m_InputBuilder.setContext(*input);
if (!input->hasMemArea())
m_InputBuilder.setMemory(*input, FileHandle::OpenMode(FileHandle::ReadOnly),
FileHandle::Permission(FileHandle::System));
return input;
}
/// ReadInput - To read an input file and append it to the input tree.
Input* IRBuilder::ReadInput(const std::string& pNameSpec) {
const sys::fs::Path* path = NULL;
// find out the real path of the namespec.
if (m_InputBuilder.getConstraint().isSharedSystem()) {
// In the system with shared object support, we can find both archive
// and shared object.
if (m_InputBuilder.getAttributes().isStatic()) {
// with --static, we must search an archive.
path = m_Module.getScript().directories().find(pNameSpec, Input::Archive);
} else {
// otherwise, with --Bdynamic, we can find either an archive or a
// shared object.
path = m_Module.getScript().directories().find(pNameSpec, Input::DynObj);
}
} else {
// In the system without shared object support, we only look for an archive
path = m_Module.getScript().directories().find(pNameSpec, Input::Archive);
}
if (path == NULL) {
fatal(diag::err_cannot_find_namespec) << pNameSpec;
return NULL;
}
m_InputBuilder.createNode<InputTree::Positional>(pNameSpec, *path);
Input* input = *m_InputBuilder.getCurrentNode();
if (!input->hasContext())
m_InputBuilder.setContext(*input);
if (!input->hasMemArea())
m_InputBuilder.setMemory(*input, FileHandle::OpenMode(FileHandle::ReadOnly),
FileHandle::Permission(FileHandle::System));
return input;
}
/// ReadInput - To read an input file and append it to the input tree.
Input* IRBuilder::ReadInput(FileHandle& pFileHandle) {
m_InputBuilder.createNode<InputTree::Positional>("file handler",
pFileHandle.path());
Input* input = *m_InputBuilder.getCurrentNode();
if (pFileHandle.path().empty()) {
m_InputBuilder.setContext(*input, false);
} else {
m_InputBuilder.setContext(*input, true);
}
m_InputBuilder.setMemory(*input, FileHandle::OpenMode(FileHandle::ReadOnly),
FileHandle::Permission(FileHandle::System));
return input;
}
/// ReadInput - To read an input file and append it to the input tree.
Input* IRBuilder::ReadInput(const std::string& pName,
void* pRawMemory,
size_t pSize) {
m_InputBuilder.createNode<InputTree::Positional>(pName, sys::fs::Path("NAN"));
Input* input = *m_InputBuilder.getCurrentNode();
m_InputBuilder.setContext(*input, false);
m_InputBuilder.setMemory(*input, pRawMemory, pSize);
return input;
}
bool IRBuilder::StartGroup() {
if (m_InputBuilder.isInGroup()) {
fatal(diag::fatal_forbid_nest_group);
return false;
}
m_InputBuilder.enterGroup();
return true;
}
bool IRBuilder::EndGroup() {
m_InputBuilder.exitGroup();
return true;
}
void IRBuilder::WholeArchive() {
m_InputBuilder.getAttributes().setWholeArchive();
}
void IRBuilder::NoWholeArchive() {
m_InputBuilder.getAttributes().unsetWholeArchive();
}
void IRBuilder::AsNeeded() {
m_InputBuilder.getAttributes().setAsNeeded();
}
void IRBuilder::NoAsNeeded() {
m_InputBuilder.getAttributes().unsetAsNeeded();
}
void IRBuilder::CopyDTNeeded() {
m_InputBuilder.getAttributes().setAddNeeded();
}
void IRBuilder::NoCopyDTNeeded() {
m_InputBuilder.getAttributes().unsetAddNeeded();
}
void IRBuilder::AgainstShared() {
m_InputBuilder.getAttributes().setDynamic();
}
void IRBuilder::AgainstStatic() {
m_InputBuilder.getAttributes().setStatic();
}
LDSection* IRBuilder::CreateELFHeader(Input& pInput,
const std::string& pName,
uint32_t pType,
uint32_t pFlag,
uint32_t pAlign) {
// Create section header
LDFileFormat::Kind kind = GetELFSectionKind(pType, pName.c_str(), pFlag);
LDSection* header = LDSection::Create(pName, kind, pType, pFlag);
header->setAlign(pAlign);
// Append section header in input
pInput.context()->appendSection(*header);
return header;
}
/// CreateSectionData - To create a section data for given pSection.
SectionData* IRBuilder::CreateSectionData(LDSection& pSection) {
assert(!pSection.hasSectionData() && "pSection already has section data.");
SectionData* sect_data = SectionData::Create(pSection);
pSection.setSectionData(sect_data);
return sect_data;
}
/// CreateRelocData - To create a relocation data for given pSection.
RelocData* IRBuilder::CreateRelocData(LDSection& pSection) {
assert(!pSection.hasRelocData() && "pSection already has relocation data.");
RelocData* reloc_data = RelocData::Create(pSection);
pSection.setRelocData(reloc_data);
return reloc_data;
}
/// CreateEhFrame - To create a eh_frame for given pSection
EhFrame* IRBuilder::CreateEhFrame(LDSection& pSection) {
assert(!pSection.hasEhFrame() && "pSection already has eh_frame.");
EhFrame* eh_frame = EhFrame::Create(pSection);
pSection.setEhFrame(eh_frame);
return eh_frame;
}
/// CreateDebugString - To create a DebugString for given pSection
DebugString* IRBuilder::CreateDebugString(LDSection& pSection) {
assert(!pSection.hasDebugString() && "pSection already has debug_str.");
DebugString* debug_str = DebugString::Create(pSection);
pSection.setDebugString(debug_str);
return debug_str;
}
/// CreateBSS - To create a bss section for given pSection
SectionData* IRBuilder::CreateBSS(LDSection& pSection) {
assert(!pSection.hasSectionData() && "pSection already has section data.");
assert((pSection.kind() == LDFileFormat::BSS) &&
"pSection is not a BSS section.");
SectionData* sect_data = SectionData::Create(pSection);
pSection.setSectionData(sect_data);
/* value, valsize, size*/
FillFragment* frag = new FillFragment(0x0, 1, pSection.size());
ObjectBuilder::AppendFragment(*frag, *sect_data);
return sect_data;
}
/// CreateRegion - To create a region fragment in the input file.
Fragment* IRBuilder::CreateRegion(Input& pInput,
size_t pOffset,
size_t pLength) {
if (!pInput.hasMemArea()) {
fatal(diag::fatal_cannot_read_input) << pInput.path();
return NULL;
}
if (0 == pLength)
return new FillFragment(0x0, 0, 0);
llvm::StringRef region = pInput.memArea()->request(pOffset, pLength);
return new RegionFragment(region);
}
/// CreateRegion - To create a region fragment wrapping the given memory
Fragment* IRBuilder::CreateRegion(void* pMemory, size_t pLength) {
if (0 == pLength)
return new FillFragment(0x0, 0, 0);
llvm::StringRef region(reinterpret_cast<const char*>(pMemory), pLength);
return new RegionFragment(region);
}
/// AppendFragment - To append pFrag to the given SectionData pSD
uint64_t IRBuilder::AppendFragment(Fragment& pFrag, SectionData& pSD) {
uint64_t size =
ObjectBuilder::AppendFragment(pFrag, pSD, pSD.getSection().align());
pSD.getSection().setSize(pSD.getSection().size() + size);
return size;
}
/// AppendRelocation - To append an relocation to the given RelocData pRD.
void IRBuilder::AppendRelocation(Relocation& pRelocation, RelocData& pRD) {
pRD.append(pRelocation);
}
/// AppendEhFrame - To append a fragment to EhFrame.
uint64_t IRBuilder::AppendEhFrame(Fragment& pFrag, EhFrame& pEhFrame) {
uint64_t size = ObjectBuilder::AppendFragment(
pFrag, *pEhFrame.getSectionData(), pEhFrame.getSection().align());
pEhFrame.getSection().setSize(pEhFrame.getSection().size() + size);
return size;
}
/// AppendEhFrame - To append a FDE to the given EhFrame pEhFram.
uint64_t IRBuilder::AppendEhFrame(EhFrame::FDE& pFDE, EhFrame& pEhFrame) {
pEhFrame.addFDE(pFDE);
pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pFDE.size());
return pFDE.size();
}
/// AppendEhFrame - To append a CIE to the given EhFrame pEhFram.
uint64_t IRBuilder::AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame) {
pEhFrame.addCIE(pCIE);
pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pCIE.size());
return pCIE.size();
}
/// AddSymbol - To add a symbol in the input file and resolve the symbol
/// immediately
LDSymbol* IRBuilder::AddSymbol(Input& pInput,
const std::string& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBind,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
LDSection* pSection,
ResolveInfo::Visibility pVis) {
// rename symbols
std::string name = pName;
if (!m_Module.getScript().renameMap().empty() &&
ResolveInfo::Undefined == pDesc) {
// If the renameMap is not empty, some symbols should be renamed.
// --wrap and --portable defines the symbol rename map.
const LinkerScript& script = m_Module.getScript();
LinkerScript::SymbolRenameMap::const_iterator renameSym =
script.renameMap().find(pName);
if (script.renameMap().end() != renameSym)
name = renameSym.getEntry()->value();
}
// Fix up the visibility if object has no export set.
if (pInput.noExport() && (pDesc != ResolveInfo::Undefined)) {
if ((pVis == ResolveInfo::Default) || (pVis == ResolveInfo::Protected)) {
pVis = ResolveInfo::Hidden;
}
}
switch (pInput.type()) {
case Input::Object: {
FragmentRef* frag = NULL;
if (pSection == NULL || ResolveInfo::Undefined == pDesc ||
ResolveInfo::Common == pDesc || ResolveInfo::Absolute == pBind ||
LDFileFormat::Ignore == pSection->kind() ||
LDFileFormat::Group == pSection->kind())
frag = FragmentRef::Null();
else
frag = FragmentRef::Create(*pSection, pValue);
LDSymbol* input_sym = addSymbolFromObject(
name, pType, pDesc, pBind, pSize, pValue, frag, pVis);
pInput.context()->addSymbol(input_sym);
return input_sym;
}
case Input::DynObj: {
return addSymbolFromDynObj(
pInput, name, pType, pDesc, pBind, pSize, pValue, pVis);
}
default: {
return NULL;
break;
}
}
return NULL;
}
LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility) {
// Step 1. calculate a Resolver::Result
// resolved_result is a triple <resolved_info, existent, override>
Resolver::Result resolved_result;
ResolveInfo old_info; // used for arrange output symbols
if (pBinding == ResolveInfo::Local) {
// if the symbol is a local symbol, create a LDSymbol for input, but do not
// resolve them.
resolved_result.info = m_Module.getNamePool().createSymbol(
pName, false, pType, pDesc, pBinding, pSize, pVisibility);
// No matter if there is a symbol with the same name, insert the symbol
// into output symbol table. So, we let the existent false.
resolved_result.existent = false;
resolved_result.overriden = true;
} else {
// if the symbol is not local, insert and resolve it immediately
m_Module.getNamePool().insertSymbol(pName,
false,
pType,
pDesc,
pBinding,
pSize,
pValue,
pVisibility,
&old_info,
resolved_result);
}
// the return ResolveInfo should not NULL
assert(resolved_result.info != NULL);
/// Step 2. create an input LDSymbol.
// create a LDSymbol for the input file.
LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
input_sym->setFragmentRef(pFragmentRef);
input_sym->setValue(pValue);
// Step 3. Set up corresponding output LDSymbol
LDSymbol* output_sym = resolved_result.info->outSymbol();
bool has_output_sym = (output_sym != NULL);
if (!resolved_result.existent || !has_output_sym) {
// it is a new symbol, the output_sym should be NULL.
assert(output_sym == NULL);
if (pType == ResolveInfo::Section) {
// if it is a section symbol, its output LDSymbol is the input LDSymbol.
output_sym = input_sym;
} else {
// if it is a new symbol, create a LDSymbol for the output
output_sym = LDSymbol::Create(*resolved_result.info);
}
resolved_result.info->setSymPtr(output_sym);
}
if (resolved_result.overriden || !has_output_sym) {
// symbol can be overriden only if it exists.
assert(output_sym != NULL);
// should override output LDSymbol
output_sym->setFragmentRef(pFragmentRef);
output_sym->setValue(pValue);
}
return input_sym;
}
LDSymbol* IRBuilder::addSymbolFromDynObj(Input& pInput,
const std::string& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
ResolveInfo::Visibility pVisibility) {
// We don't need sections of dynamic objects. So we ignore section symbols.
if (pType == ResolveInfo::Section)
return NULL;
// ignore symbols with local binding or that have internal or hidden
// visibility
if (pBinding == ResolveInfo::Local || pVisibility == ResolveInfo::Internal ||
pVisibility == ResolveInfo::Hidden)
return NULL;
// A protected symbol in a shared library must be treated as a
// normal symbol when viewed from outside the shared library.
if (pVisibility == ResolveInfo::Protected)
pVisibility = ResolveInfo::Default;
// insert symbol and resolve it immediately
// resolved_result is a triple <resolved_info, existent, override>
Resolver::Result resolved_result;
m_Module.getNamePool().insertSymbol(pName,
true,
pType,
pDesc,
pBinding,
pSize,
pValue,
pVisibility,
NULL,
resolved_result);
// the return ResolveInfo should not NULL
assert(resolved_result.info != NULL);
if (resolved_result.overriden || !resolved_result.existent)
pInput.setNeeded();
// create a LDSymbol for the input file.
LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
input_sym->setFragmentRef(FragmentRef::Null());
input_sym->setValue(pValue);
// this symbol is seen in a dynamic object, set the InDyn flag
resolved_result.info->setInDyn();
if (!resolved_result.existent) {
// we get a new symbol, leave it as NULL
resolved_result.info->setSymPtr(NULL);
}
return input_sym;
}
/// AddRelocation - add a relocation entry
///
/// All symbols should be read and resolved before calling this function.
Relocation* IRBuilder::AddRelocation(LDSection& pSection,
Relocation::Type pType,
LDSymbol& pSym,
uint32_t pOffset,
Relocation::Address pAddend) {
FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset);
Relocation* relocation = Relocation::Create(pType, *frag_ref, pAddend);
relocation->setSymInfo(pSym.resolveInfo());
pSection.getRelocData()->append(*relocation);
return relocation;
}
ResolveInfo* IRBuilder::CreateLocalSymbol(FragmentRef& pFragRef) {
// Create and add symbol to the name pool.
ResolveInfo* resolveInfo =
m_Module.getNamePool().createSymbol(/* pName */"",
/* pIsDyn */false,
ResolveInfo::Section,
ResolveInfo::Define,
ResolveInfo::Local,
/* pSize */0,
ResolveInfo::Hidden);
if (resolveInfo == nullptr) {
return nullptr;
}
// Create input symbol.
LDSymbol* inputSym = LDSymbol::Create(*resolveInfo);
if (inputSym == nullptr) {
return nullptr;
}
inputSym->setFragmentRef(FragmentRef::Create(*pFragRef.frag(),
pFragRef.offset()));
inputSym->setValue(/* pValue */0);
// The output symbol is simply an alias to the input symbol.
resolveInfo->setSymPtr(inputSym);
return resolveInfo;
}
/// AddSymbol - define an output symbol and override it immediately
template <>
LDSymbol* IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
const llvm::StringRef& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility) {
ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
LDSymbol* output_sym = NULL;
if (info == NULL) {
// the symbol is not in the pool, create a new one.
// create a ResolveInfo
Resolver::Result result;
m_Module.getNamePool().insertSymbol(pName,
false,
pType,
pDesc,
pBinding,
pSize,
pValue,
pVisibility,
NULL,
result);
assert(!result.existent);
// create a output LDSymbol
output_sym = LDSymbol::Create(*result.info);
result.info->setSymPtr(output_sym);
if (result.info->shouldForceLocal(m_Config))
m_Module.getSymbolTable().forceLocal(*output_sym);
else
m_Module.getSymbolTable().add(*output_sym);
} else {
// the symbol is already in the pool, override it
ResolveInfo old_info;
old_info.override(*info);
info->setRegular();
info->setType(pType);
info->setDesc(pDesc);
info->setBinding(pBinding);
info->setVisibility(pVisibility);
info->setIsSymbol(true);
info->setSize(pSize);
output_sym = info->outSymbol();
if (output_sym != NULL)
m_Module.getSymbolTable().arrange(*output_sym, old_info);
else {
// create a output LDSymbol
output_sym = LDSymbol::Create(*info);
info->setSymPtr(output_sym);
m_Module.getSymbolTable().add(*output_sym);
}
}
if (output_sym != NULL) {
output_sym->setFragmentRef(pFragmentRef);
output_sym->setValue(pValue);
}
return output_sym;
}
/// AddSymbol - define an output symbol and override it immediately
template <>
LDSymbol* IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
const llvm::StringRef& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility) {
ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
if (info == NULL || !(info->isUndef() || info->isDyn())) {
// only undefined symbol and dynamic symbol can make a reference.
return NULL;
}
// the symbol is already in the pool, override it
ResolveInfo old_info;
old_info.override(*info);
info->setRegular();
info->setType(pType);
info->setDesc(pDesc);
info->setBinding(pBinding);
info->setVisibility(pVisibility);
info->setIsSymbol(true);
info->setSize(pSize);
LDSymbol* output_sym = info->outSymbol();
if (output_sym != NULL) {
output_sym->setFragmentRef(pFragmentRef);
output_sym->setValue(pValue);
m_Module.getSymbolTable().arrange(*output_sym, old_info);
} else {
// create a output LDSymbol
output_sym = LDSymbol::Create(*info);
info->setSymPtr(output_sym);
m_Module.getSymbolTable().add(*output_sym);
}
return output_sym;
}
/// AddSymbol - define an output symbol and resolve it
/// immediately
template <>
LDSymbol* IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
const llvm::StringRef& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility) {
// Result is <info, existent, override>
Resolver::Result result;
ResolveInfo old_info;
m_Module.getNamePool().insertSymbol(pName,
false,
pType,
pDesc,
pBinding,
pSize,
pValue,
pVisibility,
&old_info,
result);
LDSymbol* output_sym = result.info->outSymbol();
bool has_output_sym = (output_sym != NULL);
if (!result.existent || !has_output_sym) {
output_sym = LDSymbol::Create(*result.info);
result.info->setSymPtr(output_sym);
}
if (result.overriden || !has_output_sym) {
output_sym->setFragmentRef(pFragmentRef);
output_sym->setValue(pValue);
}
// After symbol resolution, the visibility is changed to the most restrict.
// arrange the output position
if (result.info->shouldForceLocal(m_Config))
m_Module.getSymbolTable().forceLocal(*output_sym);
else if (has_output_sym)
m_Module.getSymbolTable().arrange(*output_sym, old_info);
else
m_Module.getSymbolTable().add(*output_sym);
return output_sym;
}
/// defineSymbol - define an output symbol and resolve it immediately.
template <>
LDSymbol* IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
const llvm::StringRef& pName,
ResolveInfo::Type pType,
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility) {
ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
if (info == NULL || !(info->isUndef() || info->isDyn())) {
// only undefined symbol and dynamic symbol can make a reference.
return NULL;
}
return AddSymbol<Force, Resolve>(
pName, pType, pDesc, pBinding, pSize, pValue, pFragmentRef, pVisibility);
}
} // namespace mcld