• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //===----------------------------------------------------------------------===//
ScriptFile(Kind pKind,Input & pInput,InputBuilder & pBuilder)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 
~ScriptFile()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 
dump() const74 void ScriptFile::dump() const
75 {
76   for (const_iterator it = begin(), ie = end(); it != ie; ++it)
77     (*it)->dump();
78 }
79 
activate(Module & pModule)80 void ScriptFile::activate(Module& pModule)
81 {
82   for (const_iterator it = begin(), ie = end(); it != ie; ++it)
83     (*it)->activate(pModule);
84 }
85 
addEntryPoint(const std::string & pSymbol)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 
addOutputFormatCmd(const std::string & pName)99 void ScriptFile::addOutputFormatCmd(const std::string& pName)
100 {
101   m_CommandQueue.push_back(new OutputFormatCmd(pName));
102 }
103 
addOutputFormatCmd(const std::string & pDefault,const std::string & pBig,const std::string & pLittle)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 
addGroupCmd(StringList & pStringList,GroupReader & pGroupReader,const LinkerConfig & pConfig)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 
addOutputCmd(const std::string & pFileName)119 void ScriptFile::addOutputCmd(const std::string& pFileName)
120 {
121   m_CommandQueue.push_back(new OutputCmd(pFileName));
122 }
123 
addSearchDirCmd(const std::string & pPath)124 void ScriptFile::addSearchDirCmd(const std::string& pPath)
125 {
126   m_CommandQueue.push_back(new SearchDirCmd(pPath));
127 }
128 
addOutputArchCmd(const std::string & pArch)129 void ScriptFile::addOutputArchCmd(const std::string& pArch)
130 {
131   m_CommandQueue.push_back(new OutputArchCmd(pArch));
132 }
133 
addAssertCmd(RpnExpr & pRpnExpr,const std::string & pMessage)134 void ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage)
135 {
136   m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage));
137 }
138 
addAssignment(const std::string & pSymbolName,RpnExpr & pRpnExpr,Assignment::Type pType)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 
hasSectionsCmd() const168 bool ScriptFile::hasSectionsCmd() const
169 {
170   return m_bHasSectionsCmd;
171 }
172 
enterSectionsCmd()173 void ScriptFile::enterSectionsCmd()
174 {
175   m_bHasSectionsCmd = true;
176   m_bInSectionsCmd = true;
177   m_CommandQueue.push_back(new SectionsCmd());
178 }
179 
leaveSectionsCmd()180 void ScriptFile::leaveSectionsCmd()
181 {
182   m_bInSectionsCmd = false;
183 }
184 
enterOutputSectDesc(const std::string & pName,const OutputSectDesc::Prolog & pProlog)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 
leaveOutputSectDesc(const OutputSectDesc::Epilog & pEpilog)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 
addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,const InputSectDesc::Spec & pSpec)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 
createRpnExpr()222 RpnExpr* ScriptFile::createRpnExpr()
223 {
224   m_pRpnExpr = RpnExpr::create();
225   return m_pRpnExpr;
226 }
227 
createStringList()228 StringList* ScriptFile::createStringList()
229 {
230   m_pStringList = StringList::create();
231   return m_pStringList;
232 }
233 
setAsNeeded(bool pEnable)234 void ScriptFile::setAsNeeded(bool pEnable)
235 {
236   m_bAsNeeded = pEnable;
237 }
238 
createParserStr(const char * pText,size_t pLength)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 
clearParserStrPool()248 void ScriptFile::clearParserStrPool()
249 {
250   g_ParserStrPool->clear();
251 }
252 
253