//===- InputBuilder.cpp ---------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "mcld/MC/InputBuilder.h"
#include "mcld/LinkerConfig.h"
#include "mcld/Config/Config.h"
#include "mcld/MC/ContextFactory.h"
#include "mcld/MC/InputFactory.h"
#include "mcld/Support/MemoryAreaFactory.h"
#include "mcld/Support/Path.h"
namespace mcld {
InputBuilder::InputBuilder(const LinkerConfig& pConfig)
: m_Config(pConfig),
m_pCurrentTree(NULL),
m_pMove(NULL),
m_Root(),
m_bOwnFactory(true) {
m_pInputFactory = new InputFactory(MCLD_NUM_OF_INPUTS, pConfig);
m_pContextFactory = new ContextFactory(MCLD_NUM_OF_INPUTS);
m_pMemFactory = new MemoryAreaFactory(MCLD_NUM_OF_INPUTS);
}
InputBuilder::InputBuilder(const LinkerConfig& pConfig,
InputFactory& pInputFactory,
ContextFactory& pContextFactory,
MemoryAreaFactory& pMemoryFactory,
bool pDelegate)
: m_Config(pConfig),
m_pInputFactory(&pInputFactory),
m_pMemFactory(&pMemoryFactory),
m_pContextFactory(&pContextFactory),
m_pCurrentTree(NULL),
m_pMove(NULL),
m_Root(),
m_bOwnFactory(pDelegate) {
}
InputBuilder::~InputBuilder() {
if (m_bOwnFactory) {
delete m_pInputFactory;
delete m_pContextFactory;
delete m_pMemFactory;
}
}
Input* InputBuilder::createInput(const std::string& pName,
const sys::fs::Path& pPath,
unsigned int pType,
off_t pFileOffset) {
return m_pInputFactory->produce(pName, pPath, pType, pFileOffset);
}
InputTree& InputBuilder::enterGroup() {
assert(m_pCurrentTree != NULL && m_pMove != NULL);
m_pCurrentTree->enterGroup(m_Root, *m_pMove);
m_pMove->move(m_Root);
m_ReturnStack.push(m_Root);
m_pMove = &InputTree::Downward;
return *m_pCurrentTree;
}
InputTree& InputBuilder::exitGroup() {
assert(m_pCurrentTree != NULL && m_pMove != NULL);
m_Root = m_ReturnStack.top();
m_ReturnStack.pop();
m_pMove = &InputTree::Afterward;
return *m_pCurrentTree;
}
bool InputBuilder::isInGroup() const {
return !m_ReturnStack.empty();
}
const InputTree& InputBuilder::getCurrentTree() const {
assert(m_pCurrentTree != NULL && m_pMove != NULL);
return *m_pCurrentTree;
}
InputTree& InputBuilder::getCurrentTree() {
assert(m_pCurrentTree != NULL && m_pMove != NULL);
return *m_pCurrentTree;
}
void InputBuilder::setCurrentTree(InputTree& pInputTree) {
m_pCurrentTree = &pInputTree;
m_Root = m_pCurrentTree->root();
m_pMove = &InputTree::Downward;
}
bool InputBuilder::setContext(Input& pInput, bool pCheck) {
// The object files in an archive have common path. Every object files in an
// archive needs a individual context. We identify the object files in an
// archive by its file offset. Their file offsets are not zero.
LDContext* context = NULL;
if (pInput.fileOffset() != 0 || !pCheck) {
// pInput is an object in an archive file. Produce a new context in this
// case.
context = m_pContextFactory->produce();
} else {
// Using pInput.path() to avoid from creating context for identical file
// twice.
context = m_pContextFactory->produce(pInput.path());
}
pInput.setContext(context);
return true;
}
bool InputBuilder::setMemory(Input& pInput,
FileHandle::OpenMode pMode,
FileHandle::Permission pPerm) {
MemoryArea* memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
pInput.setMemArea(memory);
return true;
}
bool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize) {
MemoryArea* memory = m_pMemFactory->produce(pMemBuffer, pSize);
pInput.setMemArea(memory);
return true;
}
const AttrConstraint& InputBuilder::getConstraint() const {
return m_Config.attribute().constraint();
}
const AttributeProxy& InputBuilder::getAttributes() const {
return m_pInputFactory->attr();
}
AttributeProxy& InputBuilder::getAttributes() {
return m_pInputFactory->attr();
}
} // namespace mcld