15ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//===- ScriptFile.cpp -----------------------------------------------------===//
25ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//
35ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//                     The MCLinker Project
45ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//
55ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood// This file is distributed under the University of Illinois Open Source
65ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood// License. See LICENSE.TXT for details.
75ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//
85ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//===----------------------------------------------------------------------===//
95ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/ScriptFile.h"
105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/ADT/HashEntry.h"
125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/ADT/HashTable.h"
135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/ADT/StringHash.h"
145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/AssertCmd.h"
155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/EntryCmd.h"
165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/GroupCmd.h"
175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/InputCmd.h"
185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/Operand.h"
195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/OutputArchCmd.h"
208a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono#include "mcld/Script/OutputCmd.h"
215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/OutputFormatCmd.h"
228a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono#include "mcld/Script/RpnExpr.h"
235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/ScriptCommand.h"
245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/SearchDirCmd.h"
255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include "mcld/Script/SectionsCmd.h"
260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include "mcld/Script/StringList.h"
270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include "mcld/Script/StrToken.h"
28b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "mcld/MC/Input.h"
2942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood#include "mcld/MC/InputBuilder.h"
3042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood#include "mcld/Support/MemoryArea.h"
31b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "mcld/InputTree.h"
325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <llvm/Support/Casting.h>
345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <llvm/Support/ManagedStatic.h>
358a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <cassert>
375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodnamespace mcld {
395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodtypedef HashEntry<std::string, void*, hash::StringCompare<std::string> >
415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    ParserStrEntry;
425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodtypedef HashTable<ParserStrEntry,
4342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood                  hash::StringHash<hash::DJB>,
4442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood                  EntryFactory<ParserStrEntry> > ParserStrPool;
4542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwoodstatic llvm::ManagedStatic<ParserStrPool> g_ParserStrPool;
4642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood
475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//===----------------------------------------------------------------------===//
48a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood// ScriptFile
495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood//===----------------------------------------------------------------------===//
505ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodScriptFile::ScriptFile(Kind pKind, Input& pInput, InputBuilder& pBuilder)
515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    : m_Kind(pKind),
525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood      m_Input(pInput),
535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood      m_Name(pInput.path().native()),
545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood      m_pInputTree(NULL),
555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood      m_Builder(pBuilder),
565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood      m_bHasSectionsCmd(false),
575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood      m_bInSectionsCmd(false),
588a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono      m_bInOutputSectDesc(false),
598a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono      m_pRpnExpr(NULL),
60f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood      m_pStringList(NULL),
61f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood      m_bAsNeeded(false) {
628a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono  // FIXME: move creation of input tree out of ScriptFile.
638a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono  m_pInputTree = new InputTree();
645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
658d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono
668d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi HironoScriptFile::~ScriptFile() {
678d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono  for (iterator it = begin(), ie = end(); it != ie; ++it) {
688d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono    if (*it != NULL)
690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood      delete *it;
700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood  }
718a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono  if (m_pInputTree != NULL)
728a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    delete m_pInputTree;
730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
74d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono
75d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hironovoid ScriptFile::dump() const {
76d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    (*it)->dump();
784a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono}
794a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono
804a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironovoid ScriptFile::activate(Module& pModule) {
814a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
824a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    (*it)->activate(pModule);
834a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono}
844a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono
854a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironovoid ScriptFile::addEntryPoint(const std::string& pSymbol) {
865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood  EntryCmd* entry = new EntryCmd(pSymbol);
8723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
8823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood  if (m_bInSectionsCmd) {
8923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    assert(!m_CommandQueue.empty());
905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    sections->push_back(entry);
925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood  } else {
930c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    m_CommandQueue.push_back(entry);
945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood  }
955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid ScriptFile::addOutputFormatCmd(const std::string& pName) {
985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood  m_CommandQueue.push_back(new OutputFormatCmd(pName));
995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid ScriptFile::addOutputFormatCmd(const std::string& pDefault,
10227afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood                                    const std::string& pBig,
10327afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood                                    const std::string& pLittle) {
1045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood  m_CommandQueue.push_back(new OutputFormatCmd(pDefault, pBig, pLittle));
1053e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood}
1060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
107532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewskivoid ScriptFile::addInputCmd(StringList& pStringList,
1086afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood                             ObjectReader& pObjectReader,
1096afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood                             ArchiveReader& pArchiveReader,
110d7221079292b17a81ec003adef06d58019d9236dDaichi Hirono                             DynObjReader& pDynObjReader,
1115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood                             const LinkerConfig& pConfig) {
11298693f674125484de8873d969c209276a6dd604bMike Lockwood  m_CommandQueue.push_back(new InputCmd(pStringList,
11398693f674125484de8873d969c209276a6dd604bMike Lockwood                                        *m_pInputTree,
114a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                                        m_Builder,
11599e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood                                        pObjectReader,
116a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                                        pArchiveReader,
11766a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono                                        pDynObjReader,
11866a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono                                        pConfig));
11966a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono}
1204fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
1214a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironovoid ScriptFile::addGroupCmd(StringList& pStringList,
12223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                             GroupReader& pGroupReader,
12327afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood                             const LinkerConfig& pConfig) {
124025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski  m_CommandQueue.push_back(new GroupCmd(
1254a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono      pStringList, *m_pInputTree, m_Builder, pGroupReader, pConfig));
1264a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono}
1274a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono
1284a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironovoid ScriptFile::addOutputCmd(const std::string& pFileName) {
1294a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono  m_CommandQueue.push_back(new OutputCmd(pFileName));
1304a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono}
131326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono
132326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hironovoid ScriptFile::addSearchDirCmd(const std::string& pPath) {
133326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono  m_CommandQueue.push_back(new SearchDirCmd(pPath));
134326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono}
135326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono
136326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hironovoid ScriptFile::addOutputArchCmd(const std::string& pArch) {
1378a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono  m_CommandQueue.push_back(new OutputArchCmd(pArch));
1388a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
1398a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
1408a7ffae09a019de7109b30c505561c453910bde1Daichi Hironovoid ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage) {
1418a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono  m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage));
1428a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
14359a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono
14459a90609cc340d2933c119aa47045a5c95530b48Daichi Hironovoid ScriptFile::addAssignment(const std::string& pSymbolName,
14559a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono                               RpnExpr& pRpnExpr,
1468a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono                               Assignment::Type pType) {
1478a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono  if (m_bInSectionsCmd) {
1488a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    assert(!m_CommandQueue.empty());
1498a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
1500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (m_bInOutputSectDesc) {
1515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood      assert(!sections->empty());
1524fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono      OutputSectDesc* output_desc =
1534a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono          llvm::cast<OutputSectDesc>(sections->back());
1544a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono      output_desc->push_back(new Assignment(Assignment::INPUT_SECTION,
1554a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                            pType,
1564a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                            *(SymOperand::create(pSymbolName)),
1574a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                            pRpnExpr));
1584a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    } else {
1594a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono      sections->push_back(new Assignment(Assignment::OUTPUT_SECTION,
1604a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                         pType,
1614a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                         *(SymOperand::create(pSymbolName)),
1625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood                                         pRpnExpr));
1630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
1645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood  } else {
1650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    m_CommandQueue.push_back(new Assignment(Assignment::OUTSIDE_SECTIONS,
1665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood                                            pType,
1675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood                                            *(SymOperand::create(pSymbolName)),
1685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood                                            pRpnExpr));
1695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood  }
1705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
172bool ScriptFile::hasSectionsCmd() const {
173  return m_bHasSectionsCmd;
174}
175
176void ScriptFile::enterSectionsCmd() {
177  m_bHasSectionsCmd = true;
178  m_bInSectionsCmd = true;
179  m_CommandQueue.push_back(new SectionsCmd());
180}
181
182void ScriptFile::leaveSectionsCmd() {
183  m_bInSectionsCmd = false;
184}
185
186void ScriptFile::enterOutputSectDesc(const std::string& pName,
187                                     const OutputSectDesc::Prolog& pProlog) {
188  assert(!m_CommandQueue.empty());
189  assert(m_bInSectionsCmd);
190  SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
191  sections->push_back(new OutputSectDesc(pName, pProlog));
192
193  m_bInOutputSectDesc = true;
194}
195
196void ScriptFile::leaveOutputSectDesc(const OutputSectDesc::Epilog& pEpilog) {
197  assert(!m_CommandQueue.empty());
198  assert(m_bInSectionsCmd);
199  SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
200
201  assert(!sections->empty() && m_bInOutputSectDesc);
202  OutputSectDesc* output_desc = llvm::cast<OutputSectDesc>(sections->back());
203  output_desc->setEpilog(pEpilog);
204
205  m_bInOutputSectDesc = false;
206}
207
208void ScriptFile::addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,
209                                  const InputSectDesc::Spec& pSpec) {
210  assert(!m_CommandQueue.empty());
211  assert(m_bInSectionsCmd);
212  SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
213
214  assert(!sections->empty() && m_bInOutputSectDesc);
215  OutputSectDesc* output_sect = llvm::cast<OutputSectDesc>(sections->back());
216
217  output_sect->push_back(new InputSectDesc(pPolicy, pSpec, *output_sect));
218}
219
220RpnExpr* ScriptFile::createRpnExpr() {
221  m_pRpnExpr = RpnExpr::create();
222  return m_pRpnExpr;
223}
224
225StringList* ScriptFile::createStringList() {
226  m_pStringList = StringList::create();
227  return m_pStringList;
228}
229
230void ScriptFile::setAsNeeded(bool pEnable) {
231  m_bAsNeeded = pEnable;
232}
233
234const std::string& ScriptFile::createParserStr(const char* pText,
235                                               size_t pLength) {
236  bool exist = false;
237  ParserStrEntry* entry =
238      g_ParserStrPool->insert(std::string(pText, pLength), exist);
239  return entry->key();
240}
241
242void ScriptFile::clearParserStrPool() {
243  g_ParserStrPool->clear();
244}
245
246}  // namespace mcld
247