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