Home | History | Annotate | Download | only in Script
      1 //===- ScriptFile.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/ScriptFile.h"
     10 
     11 #include "mcld/ADT/HashEntry.h"
     12 #include "mcld/ADT/HashTable.h"
     13 #include "mcld/ADT/StringHash.h"
     14 #include "mcld/Script/AssertCmd.h"
     15 #include "mcld/Script/EntryCmd.h"
     16 #include "mcld/Script/GroupCmd.h"
     17 #include "mcld/Script/InputCmd.h"
     18 #include "mcld/Script/Operand.h"
     19 #include "mcld/Script/OutputArchCmd.h"
     20 #include "mcld/Script/OutputCmd.h"
     21 #include "mcld/Script/OutputFormatCmd.h"
     22 #include "mcld/Script/RpnExpr.h"
     23 #include "mcld/Script/ScriptCommand.h"
     24 #include "mcld/Script/SearchDirCmd.h"
     25 #include "mcld/Script/SectionsCmd.h"
     26 #include "mcld/Script/StringList.h"
     27 #include "mcld/Script/StrToken.h"
     28 #include "mcld/MC/Input.h"
     29 #include "mcld/MC/InputBuilder.h"
     30 #include "mcld/Support/MemoryArea.h"
     31 #include "mcld/InputTree.h"
     32 
     33 #include <llvm/Support/Casting.h>
     34 #include <llvm/Support/ManagedStatic.h>
     35 
     36 #include <cassert>
     37 
     38 namespace mcld {
     39 
     40 typedef HashEntry<std::string, void*, hash::StringCompare<std::string> >
     41     ParserStrEntry;
     42 typedef HashTable<ParserStrEntry,
     43                   hash::StringHash<hash::DJB>,
     44                   EntryFactory<ParserStrEntry> > ParserStrPool;
     45 static llvm::ManagedStatic<ParserStrPool> g_ParserStrPool;
     46 
     47 //===----------------------------------------------------------------------===//
     48 // ScriptFile
     49 //===----------------------------------------------------------------------===//
     50 ScriptFile::ScriptFile(Kind pKind, Input& pInput, InputBuilder& pBuilder)
     51     : m_Kind(pKind),
     52       m_Input(pInput),
     53       m_Name(pInput.path().native()),
     54       m_pInputTree(NULL),
     55       m_Builder(pBuilder),
     56       m_bHasSectionsCmd(false),
     57       m_bInSectionsCmd(false),
     58       m_bInOutputSectDesc(false),
     59       m_pRpnExpr(NULL),
     60       m_pStringList(NULL),
     61       m_bAsNeeded(false) {
     62   // FIXME: move creation of input tree out of ScriptFile.
     63   m_pInputTree = new InputTree();
     64 }
     65 
     66 ScriptFile::~ScriptFile() {
     67   for (iterator it = begin(), ie = end(); it != ie; ++it) {
     68     if (*it != NULL)
     69       delete *it;
     70   }
     71   if (m_pInputTree != NULL)
     72     delete m_pInputTree;
     73 }
     74 
     75 void ScriptFile::dump() const {
     76   for (const_iterator it = begin(), ie = end(); it != ie; ++it)
     77     (*it)->dump();
     78 }
     79 
     80 void ScriptFile::activate(Module& pModule) {
     81   for (const_iterator it = begin(), ie = end(); it != ie; ++it)
     82     (*it)->activate(pModule);
     83 }
     84 
     85 void ScriptFile::addEntryPoint(const std::string& pSymbol) {
     86   EntryCmd* entry = new EntryCmd(pSymbol);
     87 
     88   if (m_bInSectionsCmd) {
     89     assert(!m_CommandQueue.empty());
     90     SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
     91     sections->push_back(entry);
     92   } else {
     93     m_CommandQueue.push_back(entry);
     94   }
     95 }
     96 
     97 void ScriptFile::addOutputFormatCmd(const std::string& pName) {
     98   m_CommandQueue.push_back(new OutputFormatCmd(pName));
     99 }
    100 
    101 void ScriptFile::addOutputFormatCmd(const std::string& pDefault,
    102                                     const std::string& pBig,
    103                                     const std::string& pLittle) {
    104   m_CommandQueue.push_back(new OutputFormatCmd(pDefault, pBig, pLittle));
    105 }
    106 
    107 void ScriptFile::addInputCmd(StringList& pStringList,
    108                              ObjectReader& pObjectReader,
    109                              ArchiveReader& pArchiveReader,
    110                              DynObjReader& pDynObjReader,
    111                              const LinkerConfig& pConfig) {
    112   m_CommandQueue.push_back(new InputCmd(pStringList,
    113                                         *m_pInputTree,
    114                                         m_Builder,
    115                                         pObjectReader,
    116                                         pArchiveReader,
    117                                         pDynObjReader,
    118                                         pConfig));
    119 }
    120 
    121 void ScriptFile::addGroupCmd(StringList& pStringList,
    122                              GroupReader& pGroupReader,
    123                              const LinkerConfig& pConfig) {
    124   m_CommandQueue.push_back(new GroupCmd(
    125       pStringList, *m_pInputTree, m_Builder, pGroupReader, pConfig));
    126 }
    127 
    128 void ScriptFile::addOutputCmd(const std::string& pFileName) {
    129   m_CommandQueue.push_back(new OutputCmd(pFileName));
    130 }
    131 
    132 void ScriptFile::addSearchDirCmd(const std::string& pPath) {
    133   m_CommandQueue.push_back(new SearchDirCmd(pPath));
    134 }
    135 
    136 void ScriptFile::addOutputArchCmd(const std::string& pArch) {
    137   m_CommandQueue.push_back(new OutputArchCmd(pArch));
    138 }
    139 
    140 void ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage) {
    141   m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage));
    142 }
    143 
    144 void ScriptFile::addAssignment(const std::string& pSymbolName,
    145                                RpnExpr& pRpnExpr,
    146                                Assignment::Type pType) {
    147   if (m_bInSectionsCmd) {
    148     assert(!m_CommandQueue.empty());
    149     SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
    150     if (m_bInOutputSectDesc) {
    151       assert(!sections->empty());
    152       OutputSectDesc* output_desc =
    153           llvm::cast<OutputSectDesc>(sections->back());
    154       output_desc->push_back(new Assignment(Assignment::INPUT_SECTION,
    155                                             pType,
    156                                             *(SymOperand::create(pSymbolName)),
    157                                             pRpnExpr));
    158     } else {
    159       sections->push_back(new Assignment(Assignment::OUTPUT_SECTION,
    160                                          pType,
    161                                          *(SymOperand::create(pSymbolName)),
    162                                          pRpnExpr));
    163     }
    164   } else {
    165     m_CommandQueue.push_back(new Assignment(Assignment::OUTSIDE_SECTIONS,
    166                                             pType,
    167                                             *(SymOperand::create(pSymbolName)),
    168                                             pRpnExpr));
    169   }
    170 }
    171 
    172 bool ScriptFile::hasSectionsCmd() const {
    173   return m_bHasSectionsCmd;
    174 }
    175 
    176 void ScriptFile::enterSectionsCmd() {
    177   m_bHasSectionsCmd = true;
    178   m_bInSectionsCmd = true;
    179   m_CommandQueue.push_back(new SectionsCmd());
    180 }
    181 
    182 void ScriptFile::leaveSectionsCmd() {
    183   m_bInSectionsCmd = false;
    184 }
    185 
    186 void 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 
    196 void 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 
    208 void 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 
    220 RpnExpr* ScriptFile::createRpnExpr() {
    221   m_pRpnExpr = RpnExpr::create();
    222   return m_pRpnExpr;
    223 }
    224 
    225 StringList* ScriptFile::createStringList() {
    226   m_pStringList = StringList::create();
    227   return m_pStringList;
    228 }
    229 
    230 void ScriptFile::setAsNeeded(bool pEnable) {
    231   m_bAsNeeded = pEnable;
    232 }
    233 
    234 const 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 
    242 void ScriptFile::clearParserStrPool() {
    243   g_ParserStrPool->clear();
    244 }
    245 
    246 }  // namespace mcld
    247