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 38namespace mcld { 39 40typedef HashEntry<std::string, void*, hash::StringCompare<std::string> > 41 ParserStrEntry; 42typedef HashTable<ParserStrEntry, 43 hash::StringHash<hash::DJB>, 44 EntryFactory<ParserStrEntry> > ParserStrPool; 45static llvm::ManagedStatic<ParserStrPool> g_ParserStrPool; 46 47//===----------------------------------------------------------------------===// 48// ScriptFile 49//===----------------------------------------------------------------------===// 50ScriptFile::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 66ScriptFile::~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 75void ScriptFile::dump() const { 76 for (const_iterator it = begin(), ie = end(); it != ie; ++it) 77 (*it)->dump(); 78} 79 80void ScriptFile::activate(Module& pModule) { 81 for (const_iterator it = begin(), ie = end(); it != ie; ++it) 82 (*it)->activate(pModule); 83} 84 85void 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 97void ScriptFile::addOutputFormatCmd(const std::string& pName) { 98 m_CommandQueue.push_back(new OutputFormatCmd(pName)); 99} 100 101void 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 107void 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 121void 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 128void ScriptFile::addOutputCmd(const std::string& pFileName) { 129 m_CommandQueue.push_back(new OutputCmd(pFileName)); 130} 131 132void ScriptFile::addSearchDirCmd(const std::string& pPath) { 133 m_CommandQueue.push_back(new SearchDirCmd(pPath)); 134} 135 136void ScriptFile::addOutputArchCmd(const std::string& pArch) { 137 m_CommandQueue.push_back(new OutputArchCmd(pArch)); 138} 139 140void ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage) { 141 m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage)); 142} 143 144void 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 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