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