blob: 9fb997c9d1547dffff31c29d06c7f814fe22cf54 [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceGlobalContext.h - Global context defs -----*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares aspects of the compilation that persist across
11// multiple functions.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H
16#define SUBZERO_SRC_ICEGLOBALCONTEXT_H
17
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -080018#include <array>
Jim Stichnothe4a8f402015-01-20 12:52:51 -080019#include <mutex>
Jim Stichnothfa4efea2015-01-27 05:06:03 -080020#include <thread>
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070021
Jim Stichnothf7c9a142014-04-29 10:52:43 -070022#include "IceDefs.h"
Karl Schimpf9d98d792014-10-13 15:01:08 -070023#include "IceClFlags.h"
Jan Voung3bd9f1a2014-06-18 10:50:57 -070024#include "IceIntrinsics.h"
Matt Wala1bd2fce2014-08-08 14:02:09 -070025#include "IceRNG.h"
Jim Stichnothbbca7542015-02-11 16:08:31 -080026#include "IceThreading.h"
Jim Stichnoth8363a062014-10-07 10:02:38 -070027#include "IceTimerTree.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070028#include "IceTypes.h"
Jim Stichnothfa4efea2015-01-27 05:06:03 -080029#include "IceUtils.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070030
31namespace Ice {
32
Jim Stichnoth989a7032014-08-08 10:13:44 -070033class ClFlags;
Jim Stichnothe4a8f402015-01-20 12:52:51 -080034class ConstantPool;
Jim Stichnothbbca7542015-02-11 16:08:31 -080035class EmitterWorkItem;
Karl Schimpf9d98d792014-10-13 15:01:08 -070036class FuncSigType;
Jim Stichnoth989a7032014-08-08 10:13:44 -070037
Jim Stichnothe4a8f402015-01-20 12:52:51 -080038// LockedPtr is a way to provide automatically locked access to some object.
39template <typename T> class LockedPtr {
40 LockedPtr() = delete;
41 LockedPtr(const LockedPtr &) = delete;
42 LockedPtr &operator=(const LockedPtr &) = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070043
Jim Stichnoth18735602014-09-16 19:59:35 -070044public:
Jim Stichnothe4a8f402015-01-20 12:52:51 -080045 LockedPtr(T *Value, GlobalLockType *Lock) : Value(Value), Lock(Lock) {
46 Lock->lock();
47 }
48 LockedPtr(LockedPtr &&Other) : Value(Other.Value), Lock(Other.Lock) {
49 Other.Value = nullptr;
50 Other.Lock = nullptr;
51 }
52 ~LockedPtr() { Lock->unlock(); }
53 T *operator->() const { return Value; }
Jim Stichnoth18735602014-09-16 19:59:35 -070054
55private:
Jim Stichnothe4a8f402015-01-20 12:52:51 -080056 T *Value;
57 GlobalLockType *Lock;
Jim Stichnoth18735602014-09-16 19:59:35 -070058};
59
Jim Stichnothf7c9a142014-04-29 10:52:43 -070060class GlobalContext {
Jim Stichnothc6ead202015-02-24 09:30:30 -080061 GlobalContext() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070062 GlobalContext(const GlobalContext &) = delete;
63 GlobalContext &operator=(const GlobalContext &) = delete;
64
Jim Stichnothe4a8f402015-01-20 12:52:51 -080065 // CodeStats collects rudimentary statistics during translation.
66 class CodeStats {
67 CodeStats(const CodeStats &) = delete;
68 CodeStats &operator=(const CodeStats &) = default;
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -080069#define CODESTATS_TABLE \
70 /* dump string, enum value */ \
71 X("Inst Count ", InstCount) \
72 X("Regs Saved ", RegsSaved) \
73 X("Frame Bytes ", FrameByte) \
74 X("Spills ", NumSpills) \
75 X("Fills ", NumFills)
76 //#define X(str, tag)
Jim Stichnothe4a8f402015-01-20 12:52:51 -080077
78 public:
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -080079 enum CSTag {
80#define X(str, tag) CS_##tag,
81 CODESTATS_TABLE
82#undef X
83 CS_NUM
84 };
85 CodeStats() { reset(); }
86 void reset() { Stats.fill(0); }
87 void update(CSTag Tag, uint32_t Count = 1) {
88 assert(Tag < Stats.size());
89 Stats[Tag] += Count;
90 }
91 void add(const CodeStats &Other) {
92 for (uint32_t i = 0; i < Stats.size(); ++i)
93 Stats[i] += Other.Stats[i];
94 }
Jim Stichnothe4a8f402015-01-20 12:52:51 -080095 void dump(const IceString &Name, Ostream &Str);
96
97 private:
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -080098 std::array<uint32_t, CS_NUM> Stats;
Jim Stichnothe4a8f402015-01-20 12:52:51 -080099 };
100
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800101 // TimerList is a vector of TimerStack objects, with extra methods
102 // to initialize and merge these vectors.
103 class TimerList : public std::vector<TimerStack> {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800104 TimerList(const TimerList &) = delete;
105 TimerList &operator=(const TimerList &) = delete;
106
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800107 public:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800108 TimerList() = default;
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800109 // initInto() initializes a target list of timers based on the
110 // current list. In particular, it creates the same number of
111 // timers, in the same order, with the same names, but initially
112 // empty of timing data.
113 void initInto(TimerList &Dest) const {
114 if (!ALLOW_DUMP)
115 return;
116 Dest.clear();
117 for (const TimerStack &Stack : *this) {
118 Dest.push_back(TimerStack(Stack.getName()));
119 }
120 }
121 void mergeFrom(TimerList &Src) {
122 if (!ALLOW_DUMP)
123 return;
124 assert(size() == Src.size());
125 size_type i = 0;
126 for (TimerStack &Stack : *this) {
127 assert(Stack.getName() == Src[i].getName());
128 Stack.mergeFrom(Src[i]);
129 ++i;
130 }
131 }
132 };
133
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800134 // ThreadContext contains thread-local data. This data can be
135 // combined/reduced as needed after all threads complete.
136 class ThreadContext {
137 ThreadContext(const ThreadContext &) = delete;
138 ThreadContext &operator=(const ThreadContext &) = delete;
139
140 public:
141 ThreadContext() {}
142 CodeStats StatsFunction;
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -0800143 CodeStats StatsCumulative;
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800144 TimerList Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800145 };
146
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700147public:
Karl Schimpf2f67b922015-04-22 15:20:16 -0700148 // The dump stream is a log stream while emit is the stream code
149 // is emitted to. The error stream is strictly for logging errors.
150 GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
151 ELFStreamer *ELFStreamer, const ClFlags &Flags);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700152 ~GlobalContext();
153
Karl Schimpf2f67b922015-04-22 15:20:16 -0700154 //
155 // The dump, error, and emit streams need to be used by only one
156 // thread at a time. This is done by exclusively reserving the
157 // streams via lockStr() and unlockStr(). The OstreamLocker class
158 // can be used to conveniently manage this.
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800159 //
160 // The model is that a thread grabs the stream lock, then does an
161 // arbitrary amount of work during which far-away callees may grab
162 // the stream and do something with it, and finally the thread
163 // releases the stream lock. This allows large chunks of output to
164 // be dumped or emitted without risking interleaving from multiple
165 // threads.
166 void lockStr() { StrLock.lock(); }
167 void unlockStr() { StrLock.unlock(); }
Jim Stichnoth78282f62014-07-27 23:14:00 -0700168 Ostream &getStrDump() { return *StrDump; }
Karl Schimpf2f67b922015-04-22 15:20:16 -0700169 Ostream &getStrError() { return *StrError; }
Jim Stichnoth78282f62014-07-27 23:14:00 -0700170 Ostream &getStrEmit() { return *StrEmit; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700171
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800172 LockedPtr<ErrorCode> getErrorStatus() {
173 return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock);
174 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700175
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700176 // When emitting assembly, we allow a string to be prepended to
177 // names of translated functions. This makes it easier to create an
178 // execution test against a reference translator like llc, with both
179 // translators using the same bitcode as input.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700180 IceString mangleName(const IceString &Name) const;
181
182 // Manage Constants.
183 // getConstant*() functions are not const because they might add
184 // something to the constant pool.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800185 Constant *getConstantInt(Type Ty, int64_t Value);
186 Constant *getConstantInt1(int8_t ConstantInt1);
187 Constant *getConstantInt8(int8_t ConstantInt8);
188 Constant *getConstantInt16(int16_t ConstantInt16);
189 Constant *getConstantInt32(int32_t ConstantInt32);
190 Constant *getConstantInt64(int64_t ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700191 Constant *getConstantFloat(float Value);
192 Constant *getConstantDouble(double Value);
193 // Returns a symbolic constant.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800194 Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name,
195 bool SuppressMangling);
Jan Voung261cae32015-02-01 10:31:03 -0800196 Constant *getConstantExternSym(const IceString &Name);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700197 // Returns an undef.
198 Constant *getConstantUndef(Type Ty);
199 // Returns a zero value.
200 Constant *getConstantZero(Type Ty);
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700201 // getConstantPool() returns a copy of the constant pool for
202 // constants of a given type.
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800203 ConstantList getConstantPool(Type Ty);
Jan Voung261cae32015-02-01 10:31:03 -0800204 // Returns a copy of the list of external symbols.
205 ConstantList getConstantExternSyms();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700206
Jim Stichnoth989a7032014-08-08 10:13:44 -0700207 const ClFlags &getFlags() const { return Flags; }
208
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800209 bool isIRGenerationDisabled() const {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800210 return getFlags().getDisableIRGeneration();
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800211 }
212
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700213 // Allocate data of type T using the global allocator.
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800214 template <typename T> T *allocate() { return getAllocator()->Allocate<T>(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700215
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700216 const Intrinsics &getIntrinsicsInfo() const { return IntrinsicsInfo; }
217
Matt Wala1bd2fce2014-08-08 14:02:09 -0700218 // TODO(wala,stichnot): Make the RNG play nicely with multithreaded
219 // translation.
220 RandomNumberGenerator &getRNG() { return RNG; }
221
Jan Voung08c3bcd2014-12-01 17:55:16 -0800222 ELFObjectWriter *getObjectWriter() const { return ObjectWriter.get(); }
223
Jim Stichnoth18735602014-09-16 19:59:35 -0700224 // Reset stats at the beginning of a function.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800225 void resetStats() {
226 if (ALLOW_DUMP)
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800227 ICE_TLS_GET_FIELD(TLS)->StatsFunction.reset();
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800228 }
Jim Stichnothff9c7062014-09-18 04:50:49 -0700229 void dumpStats(const IceString &Name, bool Final = false);
Jim Stichnoth18735602014-09-16 19:59:35 -0700230 void statsUpdateEmitted(uint32_t InstCount) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800231 if (!getFlags().getDumpStats())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800232 return;
Jan Voung3e5009f2015-03-24 09:04:13 -0700233 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
234 Tls->StatsFunction.update(CodeStats::CS_InstCount, InstCount);
235 Tls->StatsCumulative.update(CodeStats::CS_InstCount, InstCount);
Jim Stichnoth18735602014-09-16 19:59:35 -0700236 }
237 void statsUpdateRegistersSaved(uint32_t Num) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800238 if (!getFlags().getDumpStats())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800239 return;
Jan Voung3e5009f2015-03-24 09:04:13 -0700240 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
241 Tls->StatsFunction.update(CodeStats::CS_RegsSaved, Num);
242 Tls->StatsCumulative.update(CodeStats::CS_RegsSaved, Num);
Jim Stichnoth18735602014-09-16 19:59:35 -0700243 }
244 void statsUpdateFrameBytes(uint32_t Bytes) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800245 if (!getFlags().getDumpStats())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800246 return;
Jan Voung3e5009f2015-03-24 09:04:13 -0700247 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
248 Tls->StatsFunction.update(CodeStats::CS_FrameByte, Bytes);
249 Tls->StatsCumulative.update(CodeStats::CS_FrameByte, Bytes);
Jim Stichnoth18735602014-09-16 19:59:35 -0700250 }
251 void statsUpdateSpills() {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800252 if (!getFlags().getDumpStats())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800253 return;
Jan Voung3e5009f2015-03-24 09:04:13 -0700254 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
255 Tls->StatsFunction.update(CodeStats::CS_NumSpills);
256 Tls->StatsCumulative.update(CodeStats::CS_NumSpills);
Jim Stichnoth18735602014-09-16 19:59:35 -0700257 }
258 void statsUpdateFills() {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800259 if (!getFlags().getDumpStats())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800260 return;
Jan Voung3e5009f2015-03-24 09:04:13 -0700261 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
262 Tls->StatsFunction.update(CodeStats::CS_NumFills);
263 Tls->StatsCumulative.update(CodeStats::CS_NumFills);
Jim Stichnoth18735602014-09-16 19:59:35 -0700264 }
265
Jim Stichnoth8363a062014-10-07 10:02:38 -0700266 // These are predefined TimerStackIdT values.
Jim Stichnothdd842db2015-01-27 12:53:53 -0800267 enum TimerStackKind { TSK_Default = 0, TSK_Funcs, TSK_Num };
Jim Stichnoth8363a062014-10-07 10:02:38 -0700268
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800269 // newTimerStackID() creates a new TimerStack in the global space.
270 // It does not affect any TimerStack objects in TLS.
Jim Stichnoth8363a062014-10-07 10:02:38 -0700271 TimerStackIdT newTimerStackID(const IceString &Name);
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800272 // dumpTimers() dumps the global timer data. As such, one probably
273 // wants to call mergeTimerStacks() as a prerequisite.
Jim Stichnoth8363a062014-10-07 10:02:38 -0700274 void dumpTimers(TimerStackIdT StackID = TSK_Default,
275 bool DumpCumulative = true);
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800276 // The following methods affect only the calling thread's TLS timer
277 // data.
278 TimerIdT getTimerID(TimerStackIdT StackID, const IceString &Name);
279 void pushTimer(TimerIdT ID, TimerStackIdT StackID);
280 void popTimer(TimerIdT ID, TimerStackIdT StackID);
281 void resetTimer(TimerStackIdT StackID);
282 void setTimerName(TimerStackIdT StackID, const IceString &NewName);
Jim Stichnothc4554d72014-09-30 16:49:38 -0700283
Jim Stichnothbbca7542015-02-11 16:08:31 -0800284 // This is the first work item sequence number that the parser
285 // produces, and correspondingly the first sequence number that the
286 // emitter thread will wait for. Start numbering at 1 to leave room
287 // for a sentinel, in case e.g. we wish to inject items with a
288 // special sequence number that may be executed out of order.
289 static uint32_t getFirstSequenceNumber() { return 1; }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800290 // Adds a newly parsed and constructed function to the Cfg work
291 // queue. Notifies any idle workers that a new function is
292 // available for translating. May block if the work queue is too
293 // large, in order to control memory footprint.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800294 void optQueueBlockingPush(std::unique_ptr<Cfg> Func);
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800295 // Takes a Cfg from the work queue for translating. May block if
296 // the work queue is currently empty. Returns nullptr if there is
297 // no more work - the queue is empty and either end() has been
298 // called or the Sequential flag was set.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800299 std::unique_ptr<Cfg> optQueueBlockingPop();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800300 // Notifies that no more work will be added to the work queue.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800301 void optQueueNotifyEnd() { OptQ.notifyEnd(); }
302
303 void emitQueueBlockingPush(EmitterWorkItem *Item);
304 EmitterWorkItem *emitQueueBlockingPop();
305 void emitQueueNotifyEnd() { EmitQ.notifyEnd(); }
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800306
Jan Voung44c3a802015-03-27 16:29:08 -0700307 void initParserThread() {
308 ThreadContext *Tls = new ThreadContext();
309 auto Timers = getTimers();
310 Timers->initInto(Tls->Timers);
311 AllThreadContexts.push_back(Tls);
312 ICE_TLS_SET_FIELD(TLS, Tls);
313 }
314
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800315 void startWorkerThreads() {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800316 size_t NumWorkers = getFlags().getNumTranslationThreads();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800317 auto Timers = getTimers();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800318 for (size_t i = 0; i < NumWorkers; ++i) {
319 ThreadContext *WorkerTLS = new ThreadContext();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800320 Timers->initInto(WorkerTLS->Timers);
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800321 AllThreadContexts.push_back(WorkerTLS);
322 TranslationThreads.push_back(std::thread(
323 &GlobalContext::translateFunctionsWrapper, this, WorkerTLS));
324 }
325 if (NumWorkers) {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800326 ThreadContext *WorkerTLS = new ThreadContext();
327 Timers->initInto(WorkerTLS->Timers);
328 AllThreadContexts.push_back(WorkerTLS);
329 EmitterThreads.push_back(
330 std::thread(&GlobalContext::emitterWrapper, this, WorkerTLS));
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800331 }
332 }
333
334 void waitForWorkerThreads() {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800335 optQueueNotifyEnd();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800336 for (std::thread &Worker : TranslationThreads) {
337 Worker.join();
338 }
339 TranslationThreads.clear();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800340
341 // Only notify the emit queue to end after all the translation
342 // threads have ended.
343 emitQueueNotifyEnd();
344 for (std::thread &Worker : EmitterThreads) {
345 Worker.join();
346 }
347 EmitterThreads.clear();
348
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800349 if (ALLOW_DUMP) {
350 auto Timers = getTimers();
351 for (ThreadContext *TLS : AllThreadContexts)
352 Timers->mergeFrom(TLS->Timers);
353 }
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -0800354 if (ALLOW_DUMP) {
355 // Do a separate loop over AllThreadContexts to avoid holding
356 // two locks at once.
357 auto Stats = getStatsCumulative();
358 for (ThreadContext *TLS : AllThreadContexts)
359 Stats->add(TLS->StatsCumulative);
360 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800361 }
362
363 // Translation thread startup routine.
364 void translateFunctionsWrapper(ThreadContext *MyTLS) {
365 ICE_TLS_SET_FIELD(TLS, MyTLS);
366 translateFunctions();
367 }
368 // Translate functions from the Cfg queue until the queue is empty.
369 void translateFunctions();
370
Jim Stichnothbbca7542015-02-11 16:08:31 -0800371 // Emitter thread startup routine.
372 void emitterWrapper(ThreadContext *MyTLS) {
373 ICE_TLS_SET_FIELD(TLS, MyTLS);
374 emitItems();
375 }
376 // Emit functions and global initializers from the emitter queue
377 // until the queue is empty.
378 void emitItems();
379
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800380 // Utility function to match a symbol name against a match string.
381 // This is used in a few cases where we want to take some action on
382 // a particular function or symbol based on a command-line argument,
383 // such as changing the verbose level for a particular function. An
384 // empty Match argument means match everything. Returns true if
385 // there is a match.
386 static bool matchSymbolName(const IceString &SymbolName,
387 const IceString &Match) {
388 return Match.empty() || Match == SymbolName;
389 }
390
391private:
392 // Try to ensure mutexes are allocated on separate cache lines.
393
394 ICE_CACHELINE_BOUNDARY;
395 // Managed by getAllocator()
396 GlobalLockType AllocLock;
397 ArenaAllocator<> Allocator;
398
399 ICE_CACHELINE_BOUNDARY;
400 // Managed by getConstantPool()
401 GlobalLockType ConstPoolLock;
402 std::unique_ptr<ConstantPool> ConstPool;
403
404 ICE_CACHELINE_BOUNDARY;
405 // Managed by getErrorStatus()
406 GlobalLockType ErrorStatusLock;
407 ErrorCode ErrorStatus;
408
409 ICE_CACHELINE_BOUNDARY;
410 // Managed by getStatsCumulative()
411 GlobalLockType StatsLock;
412 CodeStats StatsCumulative;
413
414 ICE_CACHELINE_BOUNDARY;
415 // Managed by getTimers()
416 GlobalLockType TimerLock;
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800417 TimerList Timers;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800418
419 ICE_CACHELINE_BOUNDARY;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800420 // StrLock is a global lock on the dump and emit output streams.
421 typedef std::mutex StrLockType;
422 StrLockType StrLock;
Jim Stichnoth620ad732015-04-28 14:12:20 -0700423 Ostream *StrDump; // Stream for dumping / diagnostics
424 Ostream *StrEmit; // Stream for code emission
Karl Schimpf2f67b922015-04-22 15:20:16 -0700425 Ostream *StrError; // Stream for logging errors.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700426
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800427 ICE_CACHELINE_BOUNDARY;
428
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700429 Intrinsics IntrinsicsInfo;
Jim Stichnoth989a7032014-08-08 10:13:44 -0700430 const ClFlags &Flags;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800431 RandomNumberGenerator RNG; // TODO(stichnot): Move into Cfg.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800432 std::unique_ptr<ELFObjectWriter> ObjectWriter;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800433 BoundedProducerConsumerQueue<Cfg> OptQ;
434 BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ;
Jim Stichnoth217dc082014-07-11 14:06:55 -0700435
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800436 LockedPtr<ArenaAllocator<>> getAllocator() {
437 return LockedPtr<ArenaAllocator<>>(&Allocator, &AllocLock);
438 }
439 LockedPtr<ConstantPool> getConstPool() {
440 return LockedPtr<ConstantPool>(ConstPool.get(), &ConstPoolLock);
441 }
442 LockedPtr<CodeStats> getStatsCumulative() {
443 return LockedPtr<CodeStats>(&StatsCumulative, &StatsLock);
444 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800445 LockedPtr<TimerList> getTimers() {
446 return LockedPtr<TimerList>(&Timers, &TimerLock);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800447 }
448
Jim Stichnothbbca7542015-02-11 16:08:31 -0800449 llvm::SmallVector<ThreadContext *, 128> AllThreadContexts;
450 llvm::SmallVector<std::thread, 128> TranslationThreads;
451 llvm::SmallVector<std::thread, 128> EmitterThreads;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800452 // Each thread has its own TLS pointer which is also held in
453 // AllThreadContexts.
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800454 ICE_TLS_DECLARE_FIELD(ThreadContext *, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800455
Jim Stichnoth217dc082014-07-11 14:06:55 -0700456 // Private helpers for mangleName()
457 typedef llvm::SmallVector<char, 32> ManglerVector;
458 void incrementSubstitutions(ManglerVector &OldName) const;
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800459
460public:
461 static void TlsInit() { ICE_TLS_INIT_FIELD(TLS); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700462};
463
Jim Stichnothc4554d72014-09-30 16:49:38 -0700464// Helper class to push and pop a timer marker. The constructor
465// pushes a marker, and the destructor pops it. This is for
466// convenient timing of regions of code.
467class TimerMarker {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800468 TimerMarker() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700469 TimerMarker(const TimerMarker &) = delete;
470 TimerMarker &operator=(const TimerMarker &) = delete;
Jim Stichnothc4554d72014-09-30 16:49:38 -0700471
472public:
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800473 TimerMarker(TimerIdT ID, GlobalContext *Ctx,
474 TimerStackIdT StackID = GlobalContext::TSK_Default)
475 : ID(ID), Ctx(Ctx), StackID(StackID), Active(false) {
476 if (ALLOW_DUMP)
477 push();
Jim Stichnothc4554d72014-09-30 16:49:38 -0700478 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800479 TimerMarker(TimerIdT ID, const Cfg *Func,
480 TimerStackIdT StackID = GlobalContext::TSK_Default)
481 : ID(ID), Ctx(nullptr), StackID(StackID), Active(false) {
482 // Ctx gets set at the beginning of pushCfg().
483 if (ALLOW_DUMP)
484 pushCfg(Func);
485 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700486
Jim Stichnothc4554d72014-09-30 16:49:38 -0700487 ~TimerMarker() {
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800488 if (ALLOW_DUMP && Active)
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800489 Ctx->popTimer(ID, StackID);
Jim Stichnothc4554d72014-09-30 16:49:38 -0700490 }
491
492private:
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800493 void push();
494 void pushCfg(const Cfg *Func);
495 const TimerIdT ID;
496 GlobalContext *Ctx;
497 const TimerStackIdT StackID;
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800498 bool Active;
Jim Stichnothc4554d72014-09-30 16:49:38 -0700499};
500
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800501// Helper class for locking the streams and then automatically
502// unlocking them.
503class OstreamLocker {
504private:
505 OstreamLocker() = delete;
506 OstreamLocker(const OstreamLocker &) = delete;
507 OstreamLocker &operator=(const OstreamLocker &) = delete;
508
509public:
510 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); }
511 ~OstreamLocker() { Ctx->unlockStr(); }
512
513private:
514 GlobalContext *const Ctx;
515};
516
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700517} // end of namespace Ice
518
519#endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H