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 34using namespace mcld; 35 36typedef HashEntry<std::string, 37 void*, 38 hash::StringCompare<std::string> > ParserStrEntry; 39typedef HashTable<ParserStrEntry, 40 hash::StringHash<hash::DJB>, 41 EntryFactory<ParserStrEntry> > ParserStrPool; 42static llvm::ManagedStatic<ParserStrPool> g_ParserStrPool; 43 44//===----------------------------------------------------------------------===// 45// ScriptFile 46//===----------------------------------------------------------------------===// 47ScriptFile::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 64ScriptFile::~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 74void ScriptFile::dump() const 75{ 76 for (const_iterator it = begin(), ie = end(); it != ie; ++it) 77 (*it)->dump(); 78} 79 80void ScriptFile::activate(Module& pModule) 81{ 82 for (const_iterator it = begin(), ie = end(); it != ie; ++it) 83 (*it)->activate(pModule); 84} 85 86void 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 99void ScriptFile::addOutputFormatCmd(const std::string& pName) 100{ 101 m_CommandQueue.push_back(new OutputFormatCmd(pName)); 102} 103 104void 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 111void 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 119void ScriptFile::addOutputCmd(const std::string& pFileName) 120{ 121 m_CommandQueue.push_back(new OutputCmd(pFileName)); 122} 123 124void ScriptFile::addSearchDirCmd(const std::string& pPath) 125{ 126 m_CommandQueue.push_back(new SearchDirCmd(pPath)); 127} 128 129void ScriptFile::addOutputArchCmd(const std::string& pArch) 130{ 131 m_CommandQueue.push_back(new OutputArchCmd(pArch)); 132} 133 134void ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage) 135{ 136 m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage)); 137} 138 139void 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 168bool ScriptFile::hasSectionsCmd() const 169{ 170 return m_bHasSectionsCmd; 171} 172 173void ScriptFile::enterSectionsCmd() 174{ 175 m_bHasSectionsCmd = true; 176 m_bInSectionsCmd = true; 177 m_CommandQueue.push_back(new SectionsCmd()); 178} 179 180void ScriptFile::leaveSectionsCmd() 181{ 182 m_bInSectionsCmd = false; 183} 184 185void 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 196void 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 209void 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 222RpnExpr* ScriptFile::createRpnExpr() 223{ 224 m_pRpnExpr = RpnExpr::create(); 225 return m_pRpnExpr; 226} 227 228StringList* ScriptFile::createStringList() 229{ 230 m_pStringList = StringList::create(); 231 return m_pStringList; 232} 233 234void ScriptFile::setAsNeeded(bool pEnable) 235{ 236 m_bAsNeeded = pEnable; 237} 238 239const 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 248void ScriptFile::clearParserStrPool() 249{ 250 g_ParserStrPool->clear(); 251} 252 253