blob: d5766d4f57aa7b01baf5336dcf5e5ef21506990f [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 Stichnothf7c9a142014-04-29 10:52:43 -0700132 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask),
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700133 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt),
Jim Stichnoth7e571362015-01-09 11:43:26 -0800134 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter() {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800135 // Make sure thread_local fields are properly initialized before any
136 // accesses are made. Do this here instead of at the start of
137 // main() so that all clients (e.g. unit tests) can benefit for
138 // free.
139 GlobalContext::TlsInit();
140 Cfg::TlsInit();
141
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800142 // Create a new ThreadContext for the current thread. No need to
143 // lock AllThreadContexts at this point since no other threads have
144 // access yet to this GlobalContext object.
145 AllThreadContexts.push_back(new ThreadContext());
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800146 ICE_TLS_SET_FIELD(TLS, AllThreadContexts.back());
Jim Stichnoth8363a062014-10-07 10:02:38 -0700147 // Pre-register built-in stack names.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800148 if (ALLOW_DUMP) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800149 // TODO(stichnot): There needs to be a strong relationship between
150 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800151 newTimerStackID("Total across all functions");
152 newTimerStackID("Per-function summary");
153 }
Jan Voung08c3bcd2014-12-01 17:55:16 -0800154 if (Flags.UseELFWriter) {
155 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
156 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700157}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700158
Jim Stichnoth217dc082014-07-11 14:06:55 -0700159// Scan a string for S[0-9A-Z]*_ patterns and replace them with
160// S<num>_ where <num> is the next base-36 value. If a type name
161// legitimately contains that pattern, then the substitution will be
162// made in error and most likely the link will fail. In this case,
163// the test classes can be rewritten not to use that pattern, which is
164// much simpler and more reliable than implementing a full demangling
165// parser. Another substitution-in-error may occur if a type
166// identifier ends with the pattern S[0-9A-Z]*, because an immediately
167// following substitution string like "S1_" or "PS1_" may be combined
168// with the previous type.
169void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const {
170 const std::locale CLocale("C");
171 // Provide extra space in case the length of <num> increases.
172 ManglerVector NewName(OldName.size() * 2);
173 size_t OldPos = 0;
174 size_t NewPos = 0;
175 size_t OldLen = OldName.size();
176 for (; OldPos < OldLen; ++OldPos, ++NewPos) {
177 if (OldName[OldPos] == '\0')
178 break;
179 if (OldName[OldPos] == 'S') {
180 // Search forward until we find _ or invalid character (including \0).
181 bool AllZs = true;
182 bool Found = false;
183 size_t Last;
184 for (Last = OldPos + 1; Last < OldLen; ++Last) {
185 char Ch = OldName[Last];
186 if (Ch == '_') {
187 Found = true;
188 break;
189 } else if (std::isdigit(Ch) || std::isupper(Ch, CLocale)) {
190 if (Ch != 'Z')
191 AllZs = false;
192 } else {
193 // Invalid character, stop searching.
194 break;
195 }
196 }
197 if (Found) {
198 NewName[NewPos++] = OldName[OldPos++]; // 'S'
199 size_t Length = Last - OldPos;
200 // NewPos and OldPos point just past the 'S'.
201 assert(NewName[NewPos - 1] == 'S');
202 assert(OldName[OldPos - 1] == 'S');
203 assert(OldName[OldPos + Length] == '_');
204 if (AllZs) {
Jim Stichnoth78b4c0b2014-07-11 15:29:23 -0700205 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if
206 // N>0) followed by N '0' characters.
207 NewName[NewPos++] = (Length ? '1' : '0');
208 for (size_t i = 0; i < Length; ++i) {
Jim Stichnoth217dc082014-07-11 14:06:55 -0700209 NewName[NewPos++] = '0';
210 }
211 } else {
212 // Iterate right-to-left and increment the base-36 number.
213 bool Carry = true;
214 for (size_t i = 0; i < Length; ++i) {
215 size_t Offset = Length - 1 - i;
216 char Ch = OldName[OldPos + Offset];
217 if (Carry) {
218 Carry = false;
219 switch (Ch) {
220 case '9':
221 Ch = 'A';
222 break;
223 case 'Z':
224 Ch = '0';
225 Carry = true;
226 break;
227 default:
228 ++Ch;
229 break;
230 }
231 }
232 NewName[NewPos + Offset] = Ch;
233 }
234 NewPos += Length;
235 }
236 OldPos = Last;
237 // Fall through and let the '_' be copied across.
238 }
239 }
240 NewName[NewPos] = OldName[OldPos];
241 }
242 assert(NewName[NewPos] == '\0');
243 OldName = NewName;
244}
245
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700246// In this context, name mangling means to rewrite a symbol using a
247// given prefix. For a C++ symbol, nest the original symbol inside
248// the "prefix" namespace. For other symbols, just prepend the
249// prefix.
250IceString GlobalContext::mangleName(const IceString &Name) const {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700251 // An already-nested name like foo::bar() gets pushed down one
252 // level, making it equivalent to Prefix::foo::bar().
253 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
254 // A non-nested but mangled name like bar() gets nested, making it
255 // equivalent to Prefix::bar().
256 // _Z3barxyz ==> ZN6Prefix3barExyz
257 // An unmangled, extern "C" style name, gets a simple prefix:
258 // bar ==> Prefixbar
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800259 if (!ALLOW_DUMP || getTestPrefix().empty())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700260 return Name;
261
262 unsigned PrefixLength = getTestPrefix().length();
Jim Stichnoth217dc082014-07-11 14:06:55 -0700263 ManglerVector NameBase(1 + Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700264 const size_t BufLen = 30 + Name.length() + PrefixLength;
Jim Stichnoth217dc082014-07-11 14:06:55 -0700265 ManglerVector NewName(BufLen);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700266 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700267
Derek Schuff44712d12014-06-17 14:34:34 -0700268 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700269 if (ItemsParsed == 1) {
270 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
271 // (splice in "6Prefix") ^^^^^^^
Derek Schuff44712d12014-06-17 14:34:34 -0700272 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
273 getTestPrefix().c_str(), NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700274 // We ignore the snprintf return value (here and below). If we
275 // somehow miscalculated the output buffer length, the output will
276 // be truncated, but it will be truncated consistently for all
277 // mangleName() calls on the same input string.
Jim Stichnoth217dc082014-07-11 14:06:55 -0700278 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700279 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700280 }
281
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700282 // Artificially limit BaseLength to 9 digits (less than 1 billion)
283 // because sscanf behavior is undefined on integer overflow. If
284 // there are more than 9 digits (which we test by looking at the
285 // beginning of NameBase), then we consider this a failure to parse
286 // a namespace mangling, and fall back to the simple prefixing.
Derek Schuff44712d12014-06-17 14:34:34 -0700287 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data());
288 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) &&
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700289 !isdigit(NameBase[0])) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700290 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz
291 // ^^^^^^^^ ^
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700292 // (splice in "N6Prefix", and insert "E" after "3bar")
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700293 // But an "I" after the identifier indicates a template argument
294 // list terminated with "E"; insert the new "E" before/after the
295 // old "E". E.g.:
296 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz
297 // ^^^^^^^^ ^
298 // (splice in "N6Prefix", and insert "E" after "3barIabcE")
Jim Stichnoth217dc082014-07-11 14:06:55 -0700299 ManglerVector OrigName(Name.length());
300 ManglerVector OrigSuffix(Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700301 uint32_t ActualBaseLength = BaseLength;
302 if (NameBase[ActualBaseLength] == 'I') {
303 ++ActualBaseLength;
304 while (NameBase[ActualBaseLength] != 'E' &&
305 NameBase[ActualBaseLength] != '\0')
306 ++ActualBaseLength;
307 }
Derek Schuff44712d12014-06-17 14:34:34 -0700308 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700309 OrigName[ActualBaseLength] = '\0';
Derek Schuff44712d12014-06-17 14:34:34 -0700310 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
311 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
312 getTestPrefix().c_str(), BaseLength, OrigName.data(),
313 OrigSuffix.data());
Jim Stichnoth217dc082014-07-11 14:06:55 -0700314 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700315 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700316 }
317
318 // Transform bar ==> Prefixbar
319 // ^^^^^^
320 return getTestPrefix() + Name;
321}
322
Karl Schimpf9d98d792014-10-13 15:01:08 -0700323GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800324 llvm::DeleteContainerPointers(AllThreadContexts);
Karl Schimpf9d98d792014-10-13 15:01:08 -0700325}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700326
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800327// TODO(stichnot): Consider adding thread-local caches of constant
328// pool entries to reduce contention.
329
330// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800331Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
332 switch (Ty) {
333 case IceType_i1:
334 return getConstantInt1(Value);
335 case IceType_i8:
336 return getConstantInt8(Value);
337 case IceType_i16:
338 return getConstantInt16(Value);
339 case IceType_i32:
340 return getConstantInt32(Value);
341 case IceType_i64:
342 return getConstantInt64(Value);
343 default:
344 llvm_unreachable("Bad integer type for getConstant");
345 }
Jim Stichnothae953202014-12-20 06:17:49 -0800346 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700347}
348
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800349Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
350 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800351 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800352}
353
354Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800355 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800356}
357
358Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800359 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800360}
361
362Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800363 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800364}
365
366Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800367 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700368}
369
370Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800371 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700372}
373
374Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800375 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700376}
377
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800378Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700379 const IceString &Name,
380 bool SuppressMangling) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800381 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800382 this, RelocatableTuple(Offset, Name, SuppressMangling));
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700383}
384
Matt Walad8f4a7d2014-06-18 09:55:03 -0700385Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800386 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700387}
388
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800389// All locking is done by the getConstant*() target function.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700390Constant *GlobalContext::getConstantZero(Type Ty) {
391 switch (Ty) {
392 case IceType_i1:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800393 return getConstantInt1(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700394 case IceType_i8:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800395 return getConstantInt8(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700396 case IceType_i16:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800397 return getConstantInt16(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700398 case IceType_i32:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800399 return getConstantInt32(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700400 case IceType_i64:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800401 return getConstantInt64(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700402 case IceType_f32:
403 return getConstantFloat(0);
404 case IceType_f64:
405 return getConstantDouble(0);
Matt Wala928f1292014-07-07 16:50:46 -0700406 case IceType_v4i1:
407 case IceType_v8i1:
408 case IceType_v16i1:
409 case IceType_v16i8:
410 case IceType_v8i16:
411 case IceType_v4i32:
412 case IceType_v4f32: {
413 IceString Str;
414 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700415 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700416 llvm_unreachable(BaseOS.str().c_str());
417 } break;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700418 case IceType_void:
419 case IceType_NUM:
420 break;
421 }
422 llvm_unreachable("Unknown type");
423}
424
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800425ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700426 switch (Ty) {
427 case IceType_i1:
428 case IceType_i8:
429 case IceType_i16:
430 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800431 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700432 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800433 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700434 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800435 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700436 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800437 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700438 case IceType_v4i1:
439 case IceType_v8i1:
440 case IceType_v16i1:
441 case IceType_v16i8:
442 case IceType_v8i16:
443 case IceType_v4i32:
444 case IceType_v4f32: {
445 IceString Str;
446 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700447 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700448 llvm_unreachable(BaseOS.str().c_str());
449 } break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700450 case IceType_void:
451 case IceType_NUM:
452 break;
453 }
454 llvm_unreachable("Unknown type");
455}
456
Jim Stichnoth8363a062014-10-07 10:02:38 -0700457TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800458 if (!ALLOW_DUMP)
459 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800460 auto Timers = getTimers();
461 TimerStackIdT NewID = Timers->size();
462 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700463 return NewID;
464}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700465
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800466TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
467 const IceString &Name) {
468 auto Timers = getTimers();
469 assert(StackID < Timers->size());
470 return Timers->at(StackID).getTimerID(Name);
471}
472
Jim Stichnoth8363a062014-10-07 10:02:38 -0700473void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800474 auto Timers = getTimers();
475 assert(StackID < Timers->size());
476 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700477}
478
479void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800480 auto Timers = getTimers();
481 assert(StackID < Timers->size());
482 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700483}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700484
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700485void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800486 auto Timers = getTimers();
487 assert(StackID < Timers->size());
488 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700489}
490
491void GlobalContext::setTimerName(TimerStackIdT StackID,
492 const IceString &NewName) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800493 auto Timers = getTimers();
494 assert(StackID < Timers->size());
495 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700496}
497
Jim Stichnothff9c7062014-09-18 04:50:49 -0700498void GlobalContext::dumpStats(const IceString &Name, bool Final) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800499 if (!ALLOW_DUMP || !getFlags().DumpStats)
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800500 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800501 OstreamLocker OL(this);
502 if (Final) {
503 getStatsCumulative()->dump(Name, getStrDump());
504 } else {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800505 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump());
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800506 getStatsCumulative()->dump("_TOTAL_", getStrDump());
Jim Stichnoth18735602014-09-16 19:59:35 -0700507 }
508}
509
Jim Stichnoth8363a062014-10-07 10:02:38 -0700510void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800511 if (!ALLOW_DUMP)
512 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800513 auto Timers = getTimers();
514 assert(Timers->size() > StackID);
515 OstreamLocker L(this);
516 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700517}
518
519TimerMarker::TimerMarker(TimerIdT ID, const Cfg *Func)
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800520 : ID(ID), Ctx(Func->getContext()), Active(false) {
521 if (ALLOW_DUMP) {
522 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled;
523 if (Active)
524 Ctx->pushTimer(ID);
525 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700526}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700527
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800528ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800529
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700530} // end of namespace Ice