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