OLD | NEW |
---|---|
1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// | 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file defines aspects of the compilation that persist across | 10 // This file defines aspects of the compilation that persist across |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 } | 128 } |
129 | 129 |
130 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, | 130 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, |
131 ELFStreamer *ELFStr, VerboseMask Mask, | 131 ELFStreamer *ELFStr, VerboseMask Mask, |
132 TargetArch Arch, OptLevel Opt, | 132 TargetArch Arch, OptLevel Opt, |
133 IceString TestPrefix, const ClFlags &Flags) | 133 IceString TestPrefix, const ClFlags &Flags) |
134 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump), | 134 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump), |
135 StrEmit(OsEmit), VMask(Mask), Arch(Arch), Opt(Opt), | 135 StrEmit(OsEmit), VMask(Mask), Arch(Arch), Opt(Opt), |
136 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter(), | 136 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter(), |
137 CfgQ(/*MaxSize=*/Flags.NumTranslationThreads, | 137 CfgQ(/*MaxSize=*/Flags.NumTranslationThreads, |
138 /*Sequential=*/(Flags.NumTranslationThreads == 0)) { | 138 /*Sequential=*/(Flags.NumTranslationThreads == 0)), |
139 EmitQ(/*MaxSize=*/Flags.NumTranslationThreads, | |
JF
2015/02/08 00:29:47
Translation an emit thread numbers should be indep
Jim Stichnoth
2015/02/08 17:11:23
Oops, cargo-cult error.
The Sequential logic is t
| |
140 /*Sequential=*/(Flags.NumTranslationThreads == 0)) { | |
139 // Make sure thread_local fields are properly initialized before any | 141 // Make sure thread_local fields are properly initialized before any |
140 // accesses are made. Do this here instead of at the start of | 142 // accesses are made. Do this here instead of at the start of |
141 // main() so that all clients (e.g. unit tests) can benefit for | 143 // main() so that all clients (e.g. unit tests) can benefit for |
142 // free. | 144 // free. |
143 GlobalContext::TlsInit(); | 145 GlobalContext::TlsInit(); |
144 Cfg::TlsInit(); | 146 Cfg::TlsInit(); |
145 // Create a new ThreadContext for the current thread. No need to | 147 // Create a new ThreadContext for the current thread. No need to |
146 // lock AllThreadContexts at this point since no other threads have | 148 // lock AllThreadContexts at this point since no other threads have |
147 // access yet to this GlobalContext object. | 149 // access yet to this GlobalContext object. |
148 ThreadContext *MyTLS = new ThreadContext(); | 150 ThreadContext *MyTLS = new ThreadContext(); |
(...skipping 22 matching lines...) Expand all Loading... | |
171 // match the -verbose-focus command-line option. | 173 // match the -verbose-focus command-line option. |
172 if (!matchSymbolName(Func->getFunctionName(), getFlags().VerboseFocusOn)) | 174 if (!matchSymbolName(Func->getFunctionName(), getFlags().VerboseFocusOn)) |
173 Func->setVerbose(IceV_None); | 175 Func->setVerbose(IceV_None); |
174 // Disable translation if -notranslate is specified, or if the | 176 // Disable translation if -notranslate is specified, or if the |
175 // current function matches the -translate-only option. If | 177 // current function matches the -translate-only option. If |
176 // translation is disabled, just dump the high-level IR and | 178 // translation is disabled, just dump the high-level IR and |
177 // continue. | 179 // continue. |
178 if (getFlags().DisableTranslation || | 180 if (getFlags().DisableTranslation || |
179 !matchSymbolName(Func->getFunctionName(), getFlags().TranslateOnly)) { | 181 !matchSymbolName(Func->getFunctionName(), getFlags().TranslateOnly)) { |
180 Func->dump(); | 182 Func->dump(); |
183 Cfg::setCurrentCfg(nullptr); | |
181 } else { | 184 } else { |
182 Func->translate(); | 185 Func->translate(); |
186 EmitterWorkItem *Item = nullptr; | |
183 if (Func->hasError()) { | 187 if (Func->hasError()) { |
184 getErrorStatus()->assign(EC_Translation); | 188 getErrorStatus()->assign(EC_Translation); |
185 OstreamLocker L(this); | 189 OstreamLocker L(this); |
186 getStrDump() << "ICE translation error: " << Func->getError() << "\n"; | 190 getStrDump() << "ICE translation error: " << Func->getError() << "\n"; |
191 Item = new EmitterWorkItem(Func->getSequenceNumber()); | |
187 } else { | 192 } else { |
188 if (getFlags().UseIntegratedAssembler) | 193 if (getFlags().UseIntegratedAssembler) { |
189 Func->emitIAS(); | 194 Func->emitIAS(); |
190 else | 195 // The Cfg has already emitted into the assembly buffer, so |
191 Func->emit(); | 196 // stats have been fully collected into this thread's TLS. |
192 // TODO(stichnot): actually add to emit queue | 197 // Dump them before TLS is reset for the next Cfg. |
198 dumpStats(Func->getFunctionName()); | |
199 Assembler *Asm = Func->releaseAssembler(); | |
200 // Copy relevant fields into Asm before Func is deleted. | |
201 Asm->setFunctionName(Func->getFunctionName()); | |
202 Asm->setInternal(Func->getInternal()); | |
203 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm); | |
204 } else { | |
205 // The Cfg has not been emitted yet, so stats are not ready | |
206 // to be dumped. | |
207 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release()); | |
208 } | |
193 } | 209 } |
210 Cfg::setCurrentCfg(nullptr); | |
211 assert(Item); | |
212 emitQueueBlockingPush(Item); | |
213 } | |
214 // The Cfg now gets deleted as Func goes out of scope. | |
215 } | |
216 } | |
217 | |
218 namespace { | |
219 | |
220 void lowerGlobals(GlobalContext *Ctx, | |
Jim Stichnoth
2015/02/07 14:53:07
This is moved largely unchanged from Translator::l
| |
221 VariableDeclarationList *VariableDeclarations, | |
222 TargetDataLowering *DataLowering) { | |
223 TimerMarker T(TimerStack::TT_emitGlobalInitializers, Ctx); | |
224 bool DisableTranslation = Ctx->getFlags().DisableTranslation; | |
225 const bool DumpGlobalVariables = | |
226 ALLOW_DUMP && Ctx->getVerbose() && Ctx->getFlags().VerboseFocusOn.empty(); | |
227 if (Ctx->getFlags().UseELFWriter) { | |
228 // Dump all globals if requested, but don't interleave w/ emission. | |
229 if (DumpGlobalVariables) { | |
230 OstreamLocker L(Ctx); | |
231 Ostream &Stream = Ctx->getStrDump(); | |
232 for (const Ice::VariableDeclaration *Global : *VariableDeclarations) { | |
233 Global->dump(Ctx, Stream); | |
234 } | |
235 } | |
236 DataLowering->lowerGlobalsELF(*VariableDeclarations); | |
237 } else { | |
238 const IceString &TranslateOnly = Ctx->getFlags().TranslateOnly; | |
239 OstreamLocker L(Ctx); | |
240 Ostream &Stream = Ctx->getStrDump(); | |
241 for (const Ice::VariableDeclaration *Global : *VariableDeclarations) { | |
242 // Interleave dump output w/ emit output. | |
243 if (DumpGlobalVariables) | |
244 Global->dump(Ctx, Stream); | |
245 if (!DisableTranslation && | |
246 GlobalContext::matchSymbolName(Global->getName(), TranslateOnly)) | |
247 DataLowering->lowerGlobal(*Global); | |
248 } | |
249 } | |
250 } | |
251 | |
252 // Ensure Pending is large enough that Pending[Index] is valid. | |
253 void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) { | |
254 if (Index >= Pending.size()) | |
255 Pending.resize(Index + 1); | |
256 } | |
257 | |
258 } // end of anonymous namespace | |
259 | |
260 void GlobalContext::emitItems() { | |
261 const bool Threaded = getFlags().NumTranslationThreads; | |
262 // Pending is a vector containing the reassembled, ordered list of | |
263 // work items. When we're ready for the next item, we first check | |
264 // whether it's in the Pending list. If not, we take an item from | |
265 // the work queue, and if it's not the item we're waiting for, we | |
266 // insert it into Pending and repeat. The work item is deleted | |
267 // after it is processed. | |
268 std::vector<EmitterWorkItem *> Pending; | |
269 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); | |
270 while (true) { | |
271 resizePending(Pending, DesiredSequenceNumber); | |
272 // See if Pending contains DesiredSequenceNumber. | |
273 EmitterWorkItem *Item = Pending[DesiredSequenceNumber]; | |
274 if (Item == nullptr) | |
275 Item = emitQueueBlockingPop(); | |
276 if (Item == nullptr) | |
277 return; | |
278 uint32_t ItemSeq = Item->getSequenceNumber(); | |
279 if (Threaded && ItemSeq != DesiredSequenceNumber) { | |
280 resizePending(Pending, ItemSeq); | |
281 Pending[ItemSeq] = Item; | |
282 continue; | |
283 } | |
284 | |
285 ++DesiredSequenceNumber; | |
286 switch (Item->getKind()) { | |
287 case EmitterWorkItem::WI_Nop: | |
288 break; | |
289 case EmitterWorkItem::WI_GlobalInits: { | |
290 lowerGlobals(this, Item->getGlobalInits(), | |
291 TargetDataLowering::createLowering(this).get()); | |
292 } break; | |
293 case EmitterWorkItem::WI_Asm: { | |
294 Assembler *Asm = Item->getAsm(); | |
295 Asm->alignFunction(); | |
296 IceString MangledName = mangleName(Asm->getFunctionName()); | |
297 if (getFlags().UseELFWriter) { | |
298 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), | |
299 Asm); | |
300 } else { | |
301 OstreamLocker L(this); | |
302 Cfg::emitTextHeader(MangledName, this, Asm); | |
303 Asm->emitIASBytes(this); | |
304 } | |
305 } break; | |
306 case EmitterWorkItem::WI_Cfg: { | |
307 assert(!getFlags().UseIntegratedAssembler); | |
308 Cfg *Func = Item->getCfg(); | |
309 // Unfortunately, we have to temporarily install the Cfg in TLS | |
310 // because Variable::asType() uses the allocator to create the | |
311 // differently-typed copy. | |
312 Cfg::setCurrentCfg(Func); | |
313 Func->emit(); | |
314 Cfg::setCurrentCfg(nullptr); | |
194 dumpStats(Func->getFunctionName()); | 315 dumpStats(Func->getFunctionName()); |
316 } break; | |
195 } | 317 } |
196 Cfg::setCurrentCfg(nullptr); | 318 delete Item; |
197 // The Cfg now gets deleted as Func goes out of scope. | |
198 } | 319 } |
199 } | 320 } |
200 | 321 |
201 // Scan a string for S[0-9A-Z]*_ patterns and replace them with | 322 // Scan a string for S[0-9A-Z]*_ patterns and replace them with |
202 // S<num>_ where <num> is the next base-36 value. If a type name | 323 // S<num>_ where <num> is the next base-36 value. If a type name |
203 // legitimately contains that pattern, then the substitution will be | 324 // legitimately contains that pattern, then the substitution will be |
204 // made in error and most likely the link will fail. In this case, | 325 // made in error and most likely the link will fail. In this case, |
205 // the test classes can be rewritten not to use that pattern, which is | 326 // the test classes can be rewritten not to use that pattern, which is |
206 // much simpler and more reliable than implementing a full demangling | 327 // much simpler and more reliable than implementing a full demangling |
207 // parser. Another substitution-in-error may occur if a type | 328 // parser. Another substitution-in-error may occur if a type |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
547 assert(StackID < Timers->size()); | 668 assert(StackID < Timers->size()); |
548 Timers->at(StackID).setName(NewName); | 669 Timers->at(StackID).setName(NewName); |
549 } | 670 } |
550 | 671 |
551 // Note: cfgQueueBlockingPush and cfgQueueBlockingPop use unique_ptr | 672 // Note: cfgQueueBlockingPush and cfgQueueBlockingPop use unique_ptr |
552 // at the interface to take and transfer ownership, but they | 673 // at the interface to take and transfer ownership, but they |
553 // internally store the raw Cfg pointer in the work queue. This | 674 // internally store the raw Cfg pointer in the work queue. This |
554 // allows e.g. future queue optimizations such as the use of atomics | 675 // allows e.g. future queue optimizations such as the use of atomics |
555 // to modify queue elements. | 676 // to modify queue elements. |
556 void GlobalContext::cfgQueueBlockingPush(std::unique_ptr<Cfg> Func) { | 677 void GlobalContext::cfgQueueBlockingPush(std::unique_ptr<Cfg> Func) { |
678 assert(Func); | |
557 CfgQ.blockingPush(Func.release()); | 679 CfgQ.blockingPush(Func.release()); |
680 if (getFlags().NumTranslationThreads == 0) | |
681 translateFunctions(); | |
558 } | 682 } |
559 | 683 |
560 std::unique_ptr<Cfg> GlobalContext::cfgQueueBlockingPop() { | 684 std::unique_ptr<Cfg> GlobalContext::cfgQueueBlockingPop() { |
561 return std::unique_ptr<Cfg>(CfgQ.blockingPop()); | 685 return std::unique_ptr<Cfg>(CfgQ.blockingPop()); |
562 } | 686 } |
563 | 687 |
688 void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) { | |
689 assert(Item); | |
690 EmitQ.blockingPush(Item); | |
691 if (getFlags().NumTranslationThreads == 0) | |
692 emitItems(); | |
693 } | |
694 | |
695 EmitterWorkItem *GlobalContext::emitQueueBlockingPop() { | |
696 return EmitQ.blockingPop(); | |
697 } | |
698 | |
564 void GlobalContext::dumpStats(const IceString &Name, bool Final) { | 699 void GlobalContext::dumpStats(const IceString &Name, bool Final) { |
565 if (!ALLOW_DUMP || !getFlags().DumpStats) | 700 if (!ALLOW_DUMP || !getFlags().DumpStats) |
566 return; | 701 return; |
567 OstreamLocker OL(this); | 702 OstreamLocker OL(this); |
568 if (Final) { | 703 if (Final) { |
569 getStatsCumulative()->dump(Name, getStrDump()); | 704 getStatsCumulative()->dump(Name, getStrDump()); |
570 } else { | 705 } else { |
571 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump()); | 706 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump()); |
572 } | 707 } |
573 } | 708 } |
(...skipping 22 matching lines...) Expand all Loading... | |
596 Ctx->pushTimer(ID, StackID); | 731 Ctx->pushTimer(ID, StackID); |
597 } | 732 } |
598 | 733 |
599 void TimerMarker::pushCfg(const Cfg *Func) { | 734 void TimerMarker::pushCfg(const Cfg *Func) { |
600 Ctx = Func->getContext(); | 735 Ctx = Func->getContext(); |
601 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled; | 736 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled; |
602 if (Active) | 737 if (Active) |
603 Ctx->pushTimer(ID, StackID); | 738 Ctx->pushTimer(ID, StackID); |
604 } | 739 } |
605 | 740 |
741 EmitterWorkItem::~EmitterWorkItem() { | |
742 // TODO(kschimpf,stichnot): Delete GlobalInits once it is managed in | |
743 // the parser as a unique_ptr. | |
744 | |
745 // delete GlobalInits; | |
746 delete Function; | |
747 delete RawFunc; | |
748 } | |
749 | |
606 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 750 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
607 | 751 |
608 } // end of namespace Ice | 752 } // end of namespace Ice |
OLD | NEW |