19cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien//===- InputBuilder.cpp ---------------------------------------------------===//
29cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien//
39cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien//                     The MCLinker Project
49cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien//
59cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// This file is distributed under the University of Illinois Open Source
69cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// License. See LICENSE.TXT for details.
79cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien//
89cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien//===----------------------------------------------------------------------===//
99cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include "mcld/MC/InputBuilder.h"
109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include "mcld/LinkerConfig.h"
129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include "mcld/Config/Config.h"
139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include "mcld/MC/ContextFactory.h"
149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include "mcld/MC/InputFactory.h"
159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include "mcld/Support/MemoryAreaFactory.h"
169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include "mcld/Support/Path.h"
179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Leviennamespace mcld {
199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienInputBuilder::InputBuilder(const LinkerConfig& pConfig)
219cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    : m_Config(pConfig),
229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_pCurrentTree(NULL),
239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_pMove(NULL),
249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_Root(),
259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_bOwnFactory(true) {
269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pInputFactory = new InputFactory(MCLD_NUM_OF_INPUTS, pConfig);
279cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pContextFactory = new ContextFactory(MCLD_NUM_OF_INPUTS);
289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pMemFactory = new MemoryAreaFactory(MCLD_NUM_OF_INPUTS);
299cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
319cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienInputBuilder::InputBuilder(const LinkerConfig& pConfig,
329cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                           InputFactory& pInputFactory,
339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                           ContextFactory& pContextFactory,
349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                           MemoryAreaFactory& pMemoryFactory,
359cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                           bool pDelegate)
369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    : m_Config(pConfig),
379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_pInputFactory(&pInputFactory),
389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_pMemFactory(&pMemoryFactory),
399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_pContextFactory(&pContextFactory),
409cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_pCurrentTree(NULL),
419cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_pMove(NULL),
429cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_Root(),
439cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien      m_bOwnFactory(pDelegate) {
449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
459cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
469cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienInputBuilder::~InputBuilder() {
479cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  if (m_bOwnFactory) {
489cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    delete m_pInputFactory;
499cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    delete m_pContextFactory;
509cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    delete m_pMemFactory;
519cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  }
529cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
539cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
549cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienInput* InputBuilder::createInput(const std::string& pName,
559cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                                 const sys::fs::Path& pPath,
569cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                                 unsigned int pType,
579cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                                 off_t pFileOffset) {
589cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return m_pInputFactory->produce(pName, pPath, pType, pFileOffset);
599cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
609cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
619cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienInputTree& InputBuilder::enterGroup() {
629cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  assert(m_pCurrentTree != NULL && m_pMove != NULL);
639cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
649cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pCurrentTree->enterGroup(m_Root, *m_pMove);
659cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pMove->move(m_Root);
669cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_ReturnStack.push(m_Root);
679cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pMove = &InputTree::Downward;
689cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
699cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return *m_pCurrentTree;
709cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
719cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
729cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienInputTree& InputBuilder::exitGroup() {
739cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  assert(m_pCurrentTree != NULL && m_pMove != NULL);
749cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
759cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_Root = m_ReturnStack.top();
769cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_ReturnStack.pop();
779cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pMove = &InputTree::Afterward;
789cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return *m_pCurrentTree;
809cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
819cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
829cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienbool InputBuilder::isInGroup() const {
839cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return !m_ReturnStack.empty();
849cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
859cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
869cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienconst InputTree& InputBuilder::getCurrentTree() const {
879cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  assert(m_pCurrentTree != NULL && m_pMove != NULL);
889cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return *m_pCurrentTree;
899cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
909cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
919cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienInputTree& InputBuilder::getCurrentTree() {
929cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  assert(m_pCurrentTree != NULL && m_pMove != NULL);
939cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return *m_pCurrentTree;
949cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
959cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
969cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienvoid InputBuilder::setCurrentTree(InputTree& pInputTree) {
979cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pCurrentTree = &pInputTree;
989cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_Root = m_pCurrentTree->root();
999cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  m_pMove = &InputTree::Downward;
1009cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1019cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1029cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienbool InputBuilder::setContext(Input& pInput, bool pCheck) {
1039cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  // The object files in an archive have common path. Every object files in an
1049cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  // archive needs a individual context. We identify the object files in an
1059cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  // archive by its file offset. Their file offsets are not zero.
1069cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  LDContext* context = NULL;
1079cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  if (pInput.fileOffset() != 0 || !pCheck) {
1089cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    // pInput is an object in an archive file. Produce a new context in this
109329ae0639e332fa0ca85049f738776083b6dbafcBehdad Esfahbod    // case.
110329ae0639e332fa0ca85049f738776083b6dbafcBehdad Esfahbod    context = m_pContextFactory->produce();
1119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  } else {
1129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    // Using pInput.path() to avoid from creating context for identical file
1139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    // twice.
1149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    context = m_pContextFactory->produce(pInput.path());
1159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  }
1169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  pInput.setContext(context);
1189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return true;
1199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1219cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienbool InputBuilder::setMemory(Input& pInput,
1229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                             FileHandle::OpenMode pMode,
1239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                             FileHandle::Permission pPerm) {
1249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  MemoryArea* memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
1259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  pInput.setMemArea(memory);
1269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return true;
1279cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1299cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienbool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize) {
1309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  MemoryArea* memory = m_pMemFactory->produce(pMemBuffer, pSize);
1319cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  pInput.setMemArea(memory);
1329cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return true;
1339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1359cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienconst AttrConstraint& InputBuilder::getConstraint() const {
1369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return m_Config.attribute().constraint();
1379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienconst AttributeProxy& InputBuilder::getAttributes() const {
1409cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return m_pInputFactory->attr();
1419cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1429cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1439cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienAttributeProxy& InputBuilder::getAttributes() {
1449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien  return m_pInputFactory->attr();
1459cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1469cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1479cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}  // namespace mcld
148