blob: 413278fe1e35aeccbf1c6901e9bf9885c23aa2f7 [file] [log] [blame]
Jim Stichnothc4554d72014-09-30 16:49:38 -07001//===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===//
Jim Stichnothf7c9a142014-04-29 10:52:43 -07002//
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 defines aspects of the compilation that persist across
11// multiple functions.
12//
13//===----------------------------------------------------------------------===//
14
Jim Stichnoth217dc082014-07-11 14:06:55 -070015#include <ctype.h> // isdigit(), isupper()
Jan Voung839c4ce2014-07-28 15:19:43 -070016#include <locale> // locale
Jim Stichnothd2cb4362014-11-20 11:24:42 -080017#include <unordered_map>
Jim Stichnothd97c7df2014-06-04 11:57:08 -070018
Jim Stichnoth639c9212014-12-11 10:04:32 -080019#include "llvm/Support/Timer.h"
20
Jim Stichnothf7c9a142014-04-29 10:52:43 -070021#include "IceCfg.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070022#include "IceClFlags.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070023#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080024#include "IceELFObjectWriter.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070025#include "IceGlobalContext.h"
Karl Schimpf9d98d792014-10-13 15:01:08 -070026#include "IceGlobalInits.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070027#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070028#include "IceTargetLowering.h"
Jim Stichnothc4554d72014-09-30 16:49:38 -070029#include "IceTimerTree.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070030#include "IceTypes.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070031
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080032namespace std {
33template <> struct hash<Ice::RelocatableTuple> {
34 size_t operator()(const Ice::RelocatableTuple &Key) const {
35 return hash<Ice::IceString>()(Key.Name) +
36 hash<Ice::RelocOffsetT>()(Key.Offset);
Jim Stichnothd2cb4362014-11-20 11:24:42 -080037 }
38};
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080039} // end of namespace std
Jim Stichnothd2cb4362014-11-20 11:24:42 -080040
Jim Stichnothf7c9a142014-04-29 10:52:43 -070041namespace Ice {
42
43// TypePool maps constants of type KeyType (e.g. float) to pointers to
Jim Stichnothd2cb4362014-11-20 11:24:42 -080044// type ValueType (e.g. ConstantFloat).
45template <Type Ty, typename KeyType, typename ValueType> class TypePool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -070046 TypePool(const TypePool &) = delete;
47 TypePool &operator=(const TypePool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070048
49public:
Jim Stichnothf61d5b22014-05-23 13:31:24 -070050 TypePool() : NextPoolID(0) {}
Jim Stichnothd2cb4362014-11-20 11:24:42 -080051 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
52 auto Iter = Pool.find(Key);
Jim Stichnothf7c9a142014-04-29 10:52:43 -070053 if (Iter != Pool.end())
54 return Iter->second;
Jim Stichnothf61d5b22014-05-23 13:31:24 -070055 ValueType *Result = ValueType::create(Ctx, Ty, Key, NextPoolID++);
Jim Stichnothd2cb4362014-11-20 11:24:42 -080056 Pool[Key] = Result;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070057 return Result;
58 }
Jim Stichnothf61d5b22014-05-23 13:31:24 -070059 ConstantList getConstantPool() const {
60 ConstantList Constants;
61 Constants.reserve(Pool.size());
Jim Stichnothf44f3712014-10-01 14:05:51 -070062 for (auto &I : Pool)
63 Constants.push_back(I.second);
Jim Stichnothf61d5b22014-05-23 13:31:24 -070064 return Constants;
65 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070066
67private:
Jim Stichnothd2cb4362014-11-20 11:24:42 -080068 typedef std::unordered_map<KeyType, ValueType *> ContainerType;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070069 ContainerType Pool;
Jim Stichnothf61d5b22014-05-23 13:31:24 -070070 uint32_t NextPoolID;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070071};
72
Matt Walad8f4a7d2014-06-18 09:55:03 -070073// UndefPool maps ICE types to the corresponding ConstantUndef values.
74class UndefPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -070075 UndefPool(const UndefPool &) = delete;
76 UndefPool &operator=(const UndefPool &) = delete;
Matt Walad8f4a7d2014-06-18 09:55:03 -070077
78public:
Jim Stichnothd2cb4362014-11-20 11:24:42 -080079 UndefPool() : NextPoolID(0), Pool(IceType_NUM) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -070080
81 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
Jim Stichnothae953202014-12-20 06:17:49 -080082 if (Pool[Ty] == nullptr)
Jim Stichnothd2cb4362014-11-20 11:24:42 -080083 Pool[Ty] = ConstantUndef::create(Ctx, Ty, NextPoolID++);
84 return Pool[Ty];
Matt Walad8f4a7d2014-06-18 09:55:03 -070085 }
86
87private:
88 uint32_t NextPoolID;
Jim Stichnothd2cb4362014-11-20 11:24:42 -080089 std::vector<ConstantUndef *> Pool;
Matt Walad8f4a7d2014-06-18 09:55:03 -070090};
91
Jim Stichnothf7c9a142014-04-29 10:52:43 -070092// The global constant pool bundles individual pools of each type of
93// interest.
94class ConstantPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -070095 ConstantPool(const ConstantPool &) = delete;
96 ConstantPool &operator=(const ConstantPool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070097
98public:
99 ConstantPool() {}
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800100 TypePool<IceType_f32, float, ConstantFloat> Floats;
101 TypePool<IceType_f64, double, ConstantDouble> Doubles;
102 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
103 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
104 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
105 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
106 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
107 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700108 UndefPool Undefs;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700109};
110
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800111void GlobalContext::CodeStats::dump(const IceString &Name, Ostream &Str) {
Jim Stichnoth639c9212014-12-11 10:04:32 -0800112 if (!ALLOW_DUMP)
113 return;
114 Str << "|" << Name << "|Inst Count |" << InstructionsEmitted << "\n";
115 Str << "|" << Name << "|Regs Saved |" << RegistersSaved << "\n";
116 Str << "|" << Name << "|Frame Bytes |" << FrameBytes << "\n";
117 Str << "|" << Name << "|Spills |" << Spills << "\n";
118 Str << "|" << Name << "|Fills |" << Fills << "\n";
119 Str << "|" << Name << "|Spills+Fills|" << Spills + Fills << "\n";
120 Str << "|" << Name << "|Memory Usage|";
121 if (ssize_t MemUsed = llvm::TimeRecord::getCurrentTime(false).getMemUsed())
122 Str << MemUsed;
123 else
124 Str << "(requires '-track-memory')";
125 Str << "\n";
126}
127
Jan Voung08c3bcd2014-12-01 17:55:16 -0800128GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit,
129 ELFStreamer *ELFStr, VerboseMask Mask,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700130 TargetArch Arch, OptLevel Opt,
Jim Stichnoth989a7032014-08-08 10:13:44 -0700131 IceString TestPrefix, const ClFlags &Flags)
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800132 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
133 StrEmit(OsEmit), VMask(Mask), Arch(Arch), Opt(Opt),
134 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter(),
135 CfgQ(/*MaxSize=*/Flags.NumTranslationThreads,
136 /*Sequential=*/(Flags.NumTranslationThreads == 0)) {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800137 // Make sure thread_local fields are properly initialized before any
138 // accesses are made. Do this here instead of at the start of
139 // main() so that all clients (e.g. unit tests) can benefit for
140 // free.
141 GlobalContext::TlsInit();
142 Cfg::TlsInit();
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800143 // Create a new ThreadContext for the current thread. No need to
144 // lock AllThreadContexts at this point since no other threads have
145 // access yet to this GlobalContext object.
146 AllThreadContexts.push_back(new ThreadContext());
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800147 ICE_TLS_SET_FIELD(TLS, AllThreadContexts.back());
Jim Stichnoth8363a062014-10-07 10:02:38 -0700148 // Pre-register built-in stack names.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800149 if (ALLOW_DUMP) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800150 // TODO(stichnot): There needs to be a strong relationship between
151 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800152 newTimerStackID("Total across all functions");
153 newTimerStackID("Per-function summary");
154 }
Jan Voung08c3bcd2014-12-01 17:55:16 -0800155 if (Flags.UseELFWriter) {
156 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
157 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700158}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700159
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800160void GlobalContext::translateFunctions() {
161 while (Cfg *Func = cfgQueueBlockingPop()) {
162 // Reset per-function stats being accumulated in TLS.
163 resetStats();
164 // Install Func in TLS for Cfg-specific container allocators.
165 Func->updateTLS();
166 // Set verbose level to none if the current function does NOT
167 // match the -verbose-focus command-line option.
168 if (!matchSymbolName(Func->getFunctionName(), getFlags().VerboseFocusOn))
169 Func->setVerbose(IceV_None);
170 // Disable translation if -notranslate is specified, or if the
171 // current function matches the -translate-only option. If
172 // translation is disabled, just dump the high-level IR and
173 // continue.
174 if (getFlags().DisableTranslation ||
175 !matchSymbolName(Func->getFunctionName(), getFlags().TranslateOnly)) {
176 Func->dump();
177 } else {
178 Func->translate();
179 if (Func->hasError()) {
180 getErrorStatus()->assign(EC_Translation);
181 OstreamLocker L(this);
182 getStrDump() << "ICE translation error: " << Func->getError() << "\n";
183 } else {
184 if (getFlags().UseIntegratedAssembler)
185 Func->emitIAS();
186 else
187 Func->emit();
188 // TODO(stichnot): actually add to emit queue
189 }
190 // TODO(stichnot): fix multithreaded stats dumping.
191 dumpStats(Func->getFunctionName());
192 }
193 delete Func;
194 }
195}
196
Jim Stichnoth217dc082014-07-11 14:06:55 -0700197// Scan a string for S[0-9A-Z]*_ patterns and replace them with
198// S<num>_ where <num> is the next base-36 value. If a type name
199// legitimately contains that pattern, then the substitution will be
200// made in error and most likely the link will fail. In this case,
201// the test classes can be rewritten not to use that pattern, which is
202// much simpler and more reliable than implementing a full demangling
203// parser. Another substitution-in-error may occur if a type
204// identifier ends with the pattern S[0-9A-Z]*, because an immediately
205// following substitution string like "S1_" or "PS1_" may be combined
206// with the previous type.
207void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const {
208 const std::locale CLocale("C");
209 // Provide extra space in case the length of <num> increases.
210 ManglerVector NewName(OldName.size() * 2);
211 size_t OldPos = 0;
212 size_t NewPos = 0;
213 size_t OldLen = OldName.size();
214 for (; OldPos < OldLen; ++OldPos, ++NewPos) {
215 if (OldName[OldPos] == '\0')
216 break;
217 if (OldName[OldPos] == 'S') {
218 // Search forward until we find _ or invalid character (including \0).
219 bool AllZs = true;
220 bool Found = false;
221 size_t Last;
222 for (Last = OldPos + 1; Last < OldLen; ++Last) {
223 char Ch = OldName[Last];
224 if (Ch == '_') {
225 Found = true;
226 break;
227 } else if (std::isdigit(Ch) || std::isupper(Ch, CLocale)) {
228 if (Ch != 'Z')
229 AllZs = false;
230 } else {
231 // Invalid character, stop searching.
232 break;
233 }
234 }
235 if (Found) {
236 NewName[NewPos++] = OldName[OldPos++]; // 'S'
237 size_t Length = Last - OldPos;
238 // NewPos and OldPos point just past the 'S'.
239 assert(NewName[NewPos - 1] == 'S');
240 assert(OldName[OldPos - 1] == 'S');
241 assert(OldName[OldPos + Length] == '_');
242 if (AllZs) {
Jim Stichnoth78b4c0b2014-07-11 15:29:23 -0700243 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if
244 // N>0) followed by N '0' characters.
245 NewName[NewPos++] = (Length ? '1' : '0');
246 for (size_t i = 0; i < Length; ++i) {
Jim Stichnoth217dc082014-07-11 14:06:55 -0700247 NewName[NewPos++] = '0';
248 }
249 } else {
250 // Iterate right-to-left and increment the base-36 number.
251 bool Carry = true;
252 for (size_t i = 0; i < Length; ++i) {
253 size_t Offset = Length - 1 - i;
254 char Ch = OldName[OldPos + Offset];
255 if (Carry) {
256 Carry = false;
257 switch (Ch) {
258 case '9':
259 Ch = 'A';
260 break;
261 case 'Z':
262 Ch = '0';
263 Carry = true;
264 break;
265 default:
266 ++Ch;
267 break;
268 }
269 }
270 NewName[NewPos + Offset] = Ch;
271 }
272 NewPos += Length;
273 }
274 OldPos = Last;
275 // Fall through and let the '_' be copied across.
276 }
277 }
278 NewName[NewPos] = OldName[OldPos];
279 }
280 assert(NewName[NewPos] == '\0');
281 OldName = NewName;
282}
283
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700284// In this context, name mangling means to rewrite a symbol using a
285// given prefix. For a C++ symbol, nest the original symbol inside
286// the "prefix" namespace. For other symbols, just prepend the
287// prefix.
288IceString GlobalContext::mangleName(const IceString &Name) const {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700289 // An already-nested name like foo::bar() gets pushed down one
290 // level, making it equivalent to Prefix::foo::bar().
291 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
292 // A non-nested but mangled name like bar() gets nested, making it
293 // equivalent to Prefix::bar().
294 // _Z3barxyz ==> ZN6Prefix3barExyz
295 // An unmangled, extern "C" style name, gets a simple prefix:
296 // bar ==> Prefixbar
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800297 if (!ALLOW_DUMP || getTestPrefix().empty())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700298 return Name;
299
300 unsigned PrefixLength = getTestPrefix().length();
Jim Stichnoth217dc082014-07-11 14:06:55 -0700301 ManglerVector NameBase(1 + Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700302 const size_t BufLen = 30 + Name.length() + PrefixLength;
Jim Stichnoth217dc082014-07-11 14:06:55 -0700303 ManglerVector NewName(BufLen);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700304 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700305
Derek Schuff44712d12014-06-17 14:34:34 -0700306 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700307 if (ItemsParsed == 1) {
308 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
309 // (splice in "6Prefix") ^^^^^^^
Derek Schuff44712d12014-06-17 14:34:34 -0700310 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
311 getTestPrefix().c_str(), NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700312 // We ignore the snprintf return value (here and below). If we
313 // somehow miscalculated the output buffer length, the output will
314 // be truncated, but it will be truncated consistently for all
315 // mangleName() calls on the same input string.
Jim Stichnoth217dc082014-07-11 14:06:55 -0700316 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700317 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700318 }
319
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700320 // Artificially limit BaseLength to 9 digits (less than 1 billion)
321 // because sscanf behavior is undefined on integer overflow. If
322 // there are more than 9 digits (which we test by looking at the
323 // beginning of NameBase), then we consider this a failure to parse
324 // a namespace mangling, and fall back to the simple prefixing.
Derek Schuff44712d12014-06-17 14:34:34 -0700325 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data());
326 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) &&
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700327 !isdigit(NameBase[0])) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700328 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz
329 // ^^^^^^^^ ^
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700330 // (splice in "N6Prefix", and insert "E" after "3bar")
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700331 // But an "I" after the identifier indicates a template argument
332 // list terminated with "E"; insert the new "E" before/after the
333 // old "E". E.g.:
334 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz
335 // ^^^^^^^^ ^
336 // (splice in "N6Prefix", and insert "E" after "3barIabcE")
Jim Stichnoth217dc082014-07-11 14:06:55 -0700337 ManglerVector OrigName(Name.length());
338 ManglerVector OrigSuffix(Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700339 uint32_t ActualBaseLength = BaseLength;
340 if (NameBase[ActualBaseLength] == 'I') {
341 ++ActualBaseLength;
342 while (NameBase[ActualBaseLength] != 'E' &&
343 NameBase[ActualBaseLength] != '\0')
344 ++ActualBaseLength;
345 }
Derek Schuff44712d12014-06-17 14:34:34 -0700346 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700347 OrigName[ActualBaseLength] = '\0';
Derek Schuff44712d12014-06-17 14:34:34 -0700348 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
349 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
350 getTestPrefix().c_str(), BaseLength, OrigName.data(),
351 OrigSuffix.data());
Jim Stichnoth217dc082014-07-11 14:06:55 -0700352 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700353 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700354 }
355
356 // Transform bar ==> Prefixbar
357 // ^^^^^^
358 return getTestPrefix() + Name;
359}
360
Karl Schimpf9d98d792014-10-13 15:01:08 -0700361GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800362 llvm::DeleteContainerPointers(AllThreadContexts);
Karl Schimpf9d98d792014-10-13 15:01:08 -0700363}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700364
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800365// TODO(stichnot): Consider adding thread-local caches of constant
366// pool entries to reduce contention.
367
368// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800369Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
370 switch (Ty) {
371 case IceType_i1:
372 return getConstantInt1(Value);
373 case IceType_i8:
374 return getConstantInt8(Value);
375 case IceType_i16:
376 return getConstantInt16(Value);
377 case IceType_i32:
378 return getConstantInt32(Value);
379 case IceType_i64:
380 return getConstantInt64(Value);
381 default:
382 llvm_unreachable("Bad integer type for getConstant");
383 }
Jim Stichnothae953202014-12-20 06:17:49 -0800384 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700385}
386
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800387Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
388 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800389 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800390}
391
392Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800393 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800394}
395
396Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800397 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800398}
399
400Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800401 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800402}
403
404Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800405 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700406}
407
408Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800409 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700410}
411
412Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800413 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700414}
415
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800416Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700417 const IceString &Name,
418 bool SuppressMangling) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800419 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800420 this, RelocatableTuple(Offset, Name, SuppressMangling));
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700421}
422
Matt Walad8f4a7d2014-06-18 09:55:03 -0700423Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800424 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700425}
426
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800427// All locking is done by the getConstant*() target function.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700428Constant *GlobalContext::getConstantZero(Type Ty) {
429 switch (Ty) {
430 case IceType_i1:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800431 return getConstantInt1(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700432 case IceType_i8:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800433 return getConstantInt8(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700434 case IceType_i16:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800435 return getConstantInt16(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700436 case IceType_i32:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800437 return getConstantInt32(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700438 case IceType_i64:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800439 return getConstantInt64(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700440 case IceType_f32:
441 return getConstantFloat(0);
442 case IceType_f64:
443 return getConstantDouble(0);
Matt Wala928f1292014-07-07 16:50:46 -0700444 case IceType_v4i1:
445 case IceType_v8i1:
446 case IceType_v16i1:
447 case IceType_v16i8:
448 case IceType_v8i16:
449 case IceType_v4i32:
450 case IceType_v4f32: {
451 IceString Str;
452 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700453 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700454 llvm_unreachable(BaseOS.str().c_str());
455 } break;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700456 case IceType_void:
457 case IceType_NUM:
458 break;
459 }
460 llvm_unreachable("Unknown type");
461}
462
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800463ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700464 switch (Ty) {
465 case IceType_i1:
466 case IceType_i8:
467 case IceType_i16:
468 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800469 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700470 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800471 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700472 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800473 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700474 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800475 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700476 case IceType_v4i1:
477 case IceType_v8i1:
478 case IceType_v16i1:
479 case IceType_v16i8:
480 case IceType_v8i16:
481 case IceType_v4i32:
482 case IceType_v4f32: {
483 IceString Str;
484 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700485 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700486 llvm_unreachable(BaseOS.str().c_str());
487 } break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700488 case IceType_void:
489 case IceType_NUM:
490 break;
491 }
492 llvm_unreachable("Unknown type");
493}
494
Jim Stichnoth8363a062014-10-07 10:02:38 -0700495TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800496 if (!ALLOW_DUMP)
497 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800498 auto Timers = getTimers();
499 TimerStackIdT NewID = Timers->size();
500 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700501 return NewID;
502}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700503
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800504TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
505 const IceString &Name) {
506 auto Timers = getTimers();
507 assert(StackID < Timers->size());
508 return Timers->at(StackID).getTimerID(Name);
509}
510
Jim Stichnoth8363a062014-10-07 10:02:38 -0700511void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800512 // TODO(stichnot): Timers are completely broken for multithreading; fix.
513 if (getFlags().NumTranslationThreads)
514 llvm::report_fatal_error("Timers and multithreading are currently broken");
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800515 auto Timers = getTimers();
516 assert(StackID < Timers->size());
517 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700518}
519
520void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800521 // TODO(stichnot): Timers are completely broken for multithreading; fix.
522 if (getFlags().NumTranslationThreads)
523 llvm::report_fatal_error("Timers and multithreading are currently broken");
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800524 auto Timers = getTimers();
525 assert(StackID < Timers->size());
526 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700527}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700528
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700529void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800530 auto Timers = getTimers();
531 assert(StackID < Timers->size());
532 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700533}
534
535void GlobalContext::setTimerName(TimerStackIdT StackID,
536 const IceString &NewName) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800537 auto Timers = getTimers();
538 assert(StackID < Timers->size());
539 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700540}
541
Jim Stichnothff9c7062014-09-18 04:50:49 -0700542void GlobalContext::dumpStats(const IceString &Name, bool Final) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800543 if (!ALLOW_DUMP || !getFlags().DumpStats)
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800544 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800545 OstreamLocker OL(this);
546 if (Final) {
547 getStatsCumulative()->dump(Name, getStrDump());
548 } else {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800549 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump());
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800550 getStatsCumulative()->dump("_TOTAL_", getStrDump());
Jim Stichnoth18735602014-09-16 19:59:35 -0700551 }
552}
553
Jim Stichnoth8363a062014-10-07 10:02:38 -0700554void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800555 if (!ALLOW_DUMP)
556 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800557 auto Timers = getTimers();
558 assert(Timers->size() > StackID);
559 OstreamLocker L(this);
560 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700561}
562
563TimerMarker::TimerMarker(TimerIdT ID, const Cfg *Func)
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800564 : ID(ID), Ctx(Func->getContext()), Active(false) {
565 if (ALLOW_DUMP) {
566 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled;
567 if (Active)
568 Ctx->pushTimer(ID);
569 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700570}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700571
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800572ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800573
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700574} // end of namespace Ice