1//===- OutputSectDesc.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/Script/OutputSectDesc.h"
10
11#include "mcld/Script/InputSectDesc.h"
12#include "mcld/Script/RpnExpr.h"
13#include "mcld/Script/StringList.h"
14#include "mcld/Script/StrToken.h"
15#include "mcld/Support/raw_ostream.h"
16#include "mcld/LinkerScript.h"
17#include "mcld/Module.h"
18
19#include <llvm/Support/Casting.h>
20
21#include <cassert>
22
23namespace mcld {
24
25//===----------------------------------------------------------------------===//
26// OutputSectDesc
27//===----------------------------------------------------------------------===//
28OutputSectDesc::OutputSectDesc(const std::string& pName, const Prolog& pProlog)
29    : ScriptCommand(ScriptCommand::OUTPUT_SECT_DESC),
30      m_Name(pName),
31      m_Prolog(pProlog) {
32}
33
34OutputSectDesc::~OutputSectDesc() {
35  for (iterator it = begin(), ie = end(); it != ie; ++it) {
36    if (*it != NULL)
37      delete *it;
38  }
39}
40
41void OutputSectDesc::dump() const {
42  mcld::outs() << m_Name << "\t";
43
44  if (m_Prolog.hasVMA()) {
45    m_Prolog.vma().dump();
46    mcld::outs() << "\t";
47  }
48
49  switch (m_Prolog.type()) {
50    case NOLOAD:
51      mcld::outs() << "(NOLOAD)";
52      break;
53    case DSECT:
54      mcld::outs() << "(DSECT)";
55      break;
56    case COPY:
57      mcld::outs() << "(COPY)";
58      break;
59    case INFO:
60      mcld::outs() << "(INFO)";
61      break;
62    case OVERLAY:
63      mcld::outs() << "(OVERLAY)";
64      break;
65    default:
66      break;
67  }
68  mcld::outs() << ":\n";
69
70  if (m_Prolog.hasLMA()) {
71    mcld::outs() << "\tAT ( ";
72    m_Prolog.lma().dump();
73    mcld::outs() << " )\n";
74  }
75
76  if (m_Prolog.hasAlign()) {
77    mcld::outs() << "\tALIGN ( ";
78    m_Prolog.align().dump();
79    mcld::outs() << " )\n";
80  }
81
82  if (m_Prolog.hasSubAlign()) {
83    mcld::outs() << "\tSUBALIGN ( ";
84    m_Prolog.subAlign().dump();
85    mcld::outs() << " )\n";
86  }
87
88  switch (m_Prolog.constraint()) {
89    case ONLY_IF_RO:
90      mcld::outs() << "\tONLY_IF_RO\n";
91      break;
92    case ONLY_IF_RW:
93      mcld::outs() << "\tONLY_IF_RW\n";
94      break;
95    default:
96      break;
97  }
98
99  mcld::outs() << "\t{\n";
100  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
101    switch ((*it)->getKind()) {
102      case ScriptCommand::ASSIGNMENT:
103      case ScriptCommand::INPUT_SECT_DESC:
104        mcld::outs() << "\t\t";
105        (*it)->dump();
106        break;
107      default:
108        assert(0);
109        break;
110    }
111  }
112  mcld::outs() << "\t}";
113
114  if (m_Epilog.hasRegion())
115    mcld::outs() << "\t>" << m_Epilog.region();
116  if (m_Epilog.hasLMARegion())
117    mcld::outs() << "\tAT>" << m_Epilog.lmaRegion();
118
119  if (m_Epilog.hasPhdrs()) {
120    for (StringList::const_iterator it = m_Epilog.phdrs().begin(),
121                                    ie = m_Epilog.phdrs().end();
122         it != ie;
123         ++it) {
124      assert((*it)->kind() == StrToken::String);
125      mcld::outs() << ":" << (*it)->name() << " ";
126    }
127  }
128
129  if (m_Epilog.hasFillExp()) {
130    mcld::outs() << "= ";
131    m_Epilog.fillExp().dump();
132  }
133  mcld::outs() << "\n";
134}
135
136void OutputSectDesc::push_back(ScriptCommand* pCommand) {
137  switch (pCommand->getKind()) {
138    case ScriptCommand::ASSIGNMENT:
139    case ScriptCommand::INPUT_SECT_DESC:
140      m_OutputSectCmds.push_back(pCommand);
141      break;
142    default:
143      assert(0);
144      break;
145  }
146}
147
148void OutputSectDesc::setEpilog(const Epilog& pEpilog) {
149  m_Epilog.m_pRegion = pEpilog.m_pRegion;
150  m_Epilog.m_pLMARegion = pEpilog.m_pLMARegion;
151  m_Epilog.m_pPhdrs = pEpilog.m_pPhdrs;
152  m_Epilog.m_pFillExp = pEpilog.m_pFillExp;
153}
154
155void OutputSectDesc::activate(Module& pModule) {
156  // Assignment in an output section
157  OutputSectCmds assignments;
158
159  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
160    switch ((*it)->getKind()) {
161      case ScriptCommand::ASSIGNMENT:
162        assignments.push_back(*it);
163        break;
164      case ScriptCommand::INPUT_SECT_DESC: {
165        (*it)->activate(pModule);
166
167        for (iterator assign = assignments.begin(),
168                      assignEnd = assignments.end();
169             assign != assignEnd;
170             ++assign) {
171          (*assign)->activate(pModule);
172        }
173        assignments.clear();
174        break;
175      }
176      default:
177        assert(0);
178        break;
179    }
180  }
181
182  if (!assignments.empty()) {
183    InputSectDesc::Spec spec;
184    spec.m_pWildcardFile = NULL;
185    spec.m_pExcludeFiles = NULL;
186    spec.m_pWildcardSections = NULL;
187    InputSectDesc inputDesc(InputSectDesc::Keep, spec, *this);
188    pModule.getScript().sectionMap().insert(inputDesc, *this);
189
190    for (iterator assign = assignments.begin(), assignEnd = assignments.end();
191         assign != assignEnd;
192         ++assign) {
193      (*assign)->activate(pModule);
194    }
195    assignments.clear();
196  }
197}
198
199}  // namespace mcld
200