1//===- InputBuilder.cpp ---------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "mcld/MC/InputBuilder.h"
10
11#include "mcld/LinkerConfig.h"
12#include "mcld/Config/Config.h"
13#include "mcld/MC/ContextFactory.h"
14#include "mcld/MC/InputFactory.h"
15#include "mcld/Support/MemoryAreaFactory.h"
16#include "mcld/Support/Path.h"
17
18namespace mcld {
19
20InputBuilder::InputBuilder(const LinkerConfig& pConfig)
21    : m_Config(pConfig),
22      m_pCurrentTree(NULL),
23      m_pMove(NULL),
24      m_Root(),
25      m_bOwnFactory(true) {
26  m_pInputFactory = new InputFactory(MCLD_NUM_OF_INPUTS, pConfig);
27  m_pContextFactory = new ContextFactory(MCLD_NUM_OF_INPUTS);
28  m_pMemFactory = new MemoryAreaFactory(MCLD_NUM_OF_INPUTS);
29}
30
31InputBuilder::InputBuilder(const LinkerConfig& pConfig,
32                           InputFactory& pInputFactory,
33                           ContextFactory& pContextFactory,
34                           MemoryAreaFactory& pMemoryFactory,
35                           bool pDelegate)
36    : m_Config(pConfig),
37      m_pInputFactory(&pInputFactory),
38      m_pMemFactory(&pMemoryFactory),
39      m_pContextFactory(&pContextFactory),
40      m_pCurrentTree(NULL),
41      m_pMove(NULL),
42      m_Root(),
43      m_bOwnFactory(pDelegate) {
44}
45
46InputBuilder::~InputBuilder() {
47  if (m_bOwnFactory) {
48    delete m_pInputFactory;
49    delete m_pContextFactory;
50    delete m_pMemFactory;
51  }
52}
53
54Input* InputBuilder::createInput(const std::string& pName,
55                                 const sys::fs::Path& pPath,
56                                 unsigned int pType,
57                                 off_t pFileOffset) {
58  return m_pInputFactory->produce(pName, pPath, pType, pFileOffset);
59}
60
61InputTree& InputBuilder::enterGroup() {
62  assert(m_pCurrentTree != NULL && m_pMove != NULL);
63
64  m_pCurrentTree->enterGroup(m_Root, *m_pMove);
65  m_pMove->move(m_Root);
66  m_ReturnStack.push(m_Root);
67  m_pMove = &InputTree::Downward;
68
69  return *m_pCurrentTree;
70}
71
72InputTree& InputBuilder::exitGroup() {
73  assert(m_pCurrentTree != NULL && m_pMove != NULL);
74
75  m_Root = m_ReturnStack.top();
76  m_ReturnStack.pop();
77  m_pMove = &InputTree::Afterward;
78
79  return *m_pCurrentTree;
80}
81
82bool InputBuilder::isInGroup() const {
83  return !m_ReturnStack.empty();
84}
85
86const InputTree& InputBuilder::getCurrentTree() const {
87  assert(m_pCurrentTree != NULL && m_pMove != NULL);
88  return *m_pCurrentTree;
89}
90
91InputTree& InputBuilder::getCurrentTree() {
92  assert(m_pCurrentTree != NULL && m_pMove != NULL);
93  return *m_pCurrentTree;
94}
95
96void InputBuilder::setCurrentTree(InputTree& pInputTree) {
97  m_pCurrentTree = &pInputTree;
98  m_Root = m_pCurrentTree->root();
99  m_pMove = &InputTree::Downward;
100}
101
102bool InputBuilder::setContext(Input& pInput, bool pCheck) {
103  // The object files in an archive have common path. Every object files in an
104  // archive needs a individual context. We identify the object files in an
105  // archive by its file offset. Their file offsets are not zero.
106  LDContext* context = NULL;
107  if (pInput.fileOffset() != 0 || !pCheck) {
108    // pInput is an object in an archive file. Produce a new context in this
109    // case.
110    context = m_pContextFactory->produce();
111  } else {
112    // Using pInput.path() to avoid from creating context for identical file
113    // twice.
114    context = m_pContextFactory->produce(pInput.path());
115  }
116
117  pInput.setContext(context);
118  return true;
119}
120
121bool InputBuilder::setMemory(Input& pInput,
122                             FileHandle::OpenMode pMode,
123                             FileHandle::Permission pPerm) {
124  MemoryArea* memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
125  pInput.setMemArea(memory);
126  return true;
127}
128
129bool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize) {
130  MemoryArea* memory = m_pMemFactory->produce(pMemBuffer, pSize);
131  pInput.setMemArea(memory);
132  return true;
133}
134
135const AttrConstraint& InputBuilder::getConstraint() const {
136  return m_Config.attribute().constraint();
137}
138
139const AttributeProxy& InputBuilder::getAttributes() const {
140  return m_pInputFactory->attr();
141}
142
143AttributeProxy& InputBuilder::getAttributes() {
144  return m_pInputFactory->attr();
145}
146
147}  // namespace mcld
148