blob: 8742f696de44cec646c4ecd2a476641715900bde [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
John Porto67f8de92015-06-25 10:14:17 -070015#include "IceGlobalContext.h"
Jim Stichnoth639c9212014-12-11 10:04:32 -080016
Jim Stichnothf7c9a142014-04-29 10:52:43 -070017#include "IceCfg.h"
John Portof8b4cc82015-06-09 18:06:19 -070018#include "IceCfgNode.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070019#include "IceClFlags.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070020#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080021#include "IceELFObjectWriter.h"
Karl Schimpf9d98d792014-10-13 15:01:08 -070022#include "IceGlobalInits.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070023#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070024#include "IceTargetLowering.h"
Jim Stichnothc4554d72014-09-30 16:49:38 -070025#include "IceTimerTree.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070026#include "IceTypes.h"
John Porto67f8de92015-06-25 10:14:17 -070027#include "llvm/Support/Timer.h"
28
29#include <ctype.h> // isdigit(), isupper()
30#include <locale> // locale
31#include <unordered_map>
32
Jim Stichnothf7c9a142014-04-29 10:52:43 -070033
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080034namespace std {
35template <> struct hash<Ice::RelocatableTuple> {
36 size_t operator()(const Ice::RelocatableTuple &Key) const {
37 return hash<Ice::IceString>()(Key.Name) +
38 hash<Ice::RelocOffsetT>()(Key.Offset);
Jim Stichnothd2cb4362014-11-20 11:24:42 -080039 }
40};
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080041} // end of namespace std
Jim Stichnothd2cb4362014-11-20 11:24:42 -080042
Jim Stichnothf7c9a142014-04-29 10:52:43 -070043namespace Ice {
44
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070045namespace {
46
47// Define the key comparison function for the constant pool's
48// unordered_map, but only for key types of interest: integer types,
49// floating point types, and the special RelocatableTuple.
50template <typename KeyType, class Enable = void> struct KeyCompare {};
51
52template <typename KeyType>
53struct KeyCompare<KeyType,
54 typename std::enable_if<
55 std::is_integral<KeyType>::value ||
56 std::is_same<KeyType, RelocatableTuple>::value>::type> {
57 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
58 return Value1 == Value2;
59 }
60};
61template <typename KeyType>
62struct KeyCompare<KeyType, typename std::enable_if<
63 std::is_floating_point<KeyType>::value>::type> {
64 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
65 return !memcmp(&Value1, &Value2, sizeof(KeyType));
66 }
67};
68
Jim Stichnoth6e293c82015-04-09 09:11:18 -070069// Define a key comparison function for sorting the constant pool's
70// values after they are dumped to a vector. This covers integer
71// types, floating point types, and ConstantRelocatable values.
72template <typename ValueType, class Enable = void> struct KeyCompareLess {};
73
74template <typename ValueType>
75struct KeyCompareLess<ValueType,
76 typename std::enable_if<std::is_floating_point<
77 typename ValueType::PrimType>::value>::type> {
78 bool operator()(const Constant *Const1, const Constant *Const2) const {
79 typedef uint64_t CompareType;
80 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType),
81 "Expected floating-point type of width 64-bit or less");
82 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
83 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
84 // We avoid "V1<V2" because of NaN.
85 // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the
86 // endian-ness of the host system running Subzero.
87 // Instead, compare the result of bit_cast to uint64_t.
88 uint64_t I1 = 0, I2 = 0;
89 memcpy(&I1, &V1, sizeof(V1));
90 memcpy(&I2, &V2, sizeof(V2));
91 return I1 < I2;
92 }
93};
94template <typename ValueType>
95struct KeyCompareLess<ValueType,
96 typename std::enable_if<std::is_integral<
97 typename ValueType::PrimType>::value>::type> {
98 bool operator()(const Constant *Const1, const Constant *Const2) const {
99 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
100 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
101 return V1 < V2;
102 }
103};
104template <typename ValueType>
105struct KeyCompareLess<
106 ValueType, typename std::enable_if<
107 std::is_same<ValueType, ConstantRelocatable>::value>::type> {
108 bool operator()(const Constant *Const1, const Constant *Const2) const {
109 auto V1 = llvm::cast<ValueType>(Const1);
110 auto V2 = llvm::cast<ValueType>(Const2);
111 if (V1->getName() == V2->getName())
112 return V1->getOffset() < V2->getOffset();
113 return V1->getName() < V2->getName();
114 }
115};
116
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700117// TypePool maps constants of type KeyType (e.g. float) to pointers to
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800118// type ValueType (e.g. ConstantFloat).
119template <Type Ty, typename KeyType, typename ValueType> class TypePool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700120 TypePool(const TypePool &) = delete;
121 TypePool &operator=(const TypePool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700122
123public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700124 TypePool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800125 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
126 auto Iter = Pool.find(Key);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700127 if (Iter != Pool.end())
128 return Iter->second;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700129 ValueType *Result = ValueType::create(Ctx, Ty, Key, NextPoolID++);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800130 Pool[Key] = Result;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700131 return Result;
132 }
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700133 ConstantList getConstantPool() const {
134 ConstantList Constants;
135 Constants.reserve(Pool.size());
Jim Stichnothf44f3712014-10-01 14:05:51 -0700136 for (auto &I : Pool)
137 Constants.push_back(I.second);
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700138 // The sort (and its KeyCompareLess machinery) is not strictly
139 // necessary, but is desirable for producing output that is
140 // deterministic across unordered_map::iterator implementations.
141 std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>());
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700142 return Constants;
143 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700144
145private:
Jim Stichnoth5bfe2152015-03-19 13:51:56 -0700146 // Use the default hash function, and a custom key comparison
147 // function. The key comparison function for floating point
148 // variables can't use the default == based implementation because
149 // of special C++ semantics regarding +0.0, -0.0, and NaN
150 // comparison. However, it's OK to use the default hash for
151 // floating point values because KeyCompare is the final source of
152 // truth - in the worst case a "false" collision must be resolved.
153 typedef std::unordered_map<KeyType, ValueType *, std::hash<KeyType>,
154 KeyCompare<KeyType>> ContainerType;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700155 ContainerType Pool;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700156 uint32_t NextPoolID = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700157};
158
Matt Walad8f4a7d2014-06-18 09:55:03 -0700159// UndefPool maps ICE types to the corresponding ConstantUndef values.
160class UndefPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700161 UndefPool(const UndefPool &) = delete;
162 UndefPool &operator=(const UndefPool &) = delete;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700163
164public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700165 UndefPool() : Pool(IceType_NUM) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700166
167 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
Jim Stichnothae953202014-12-20 06:17:49 -0800168 if (Pool[Ty] == nullptr)
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800169 Pool[Ty] = ConstantUndef::create(Ctx, Ty, NextPoolID++);
170 return Pool[Ty];
Matt Walad8f4a7d2014-06-18 09:55:03 -0700171 }
172
173private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700174 uint32_t NextPoolID = 0;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800175 std::vector<ConstantUndef *> Pool;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700176};
177
Jim Stichnoth5bfe2152015-03-19 13:51:56 -0700178} // end of anonymous namespace
179
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700180// The global constant pool bundles individual pools of each type of
181// interest.
182class ConstantPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700183 ConstantPool(const ConstantPool &) = delete;
184 ConstantPool &operator=(const ConstantPool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700185
186public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700187 ConstantPool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800188 TypePool<IceType_f32, float, ConstantFloat> Floats;
189 TypePool<IceType_f64, double, ConstantDouble> Doubles;
190 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
191 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
192 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
193 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
194 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
195 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
Jan Voung261cae32015-02-01 10:31:03 -0800196 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable>
197 ExternRelocatables;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700198 UndefPool Undefs;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700199};
200
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800201void GlobalContext::CodeStats::dump(const IceString &Name, Ostream &Str) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700202 if (!BuildDefs::dump())
Jim Stichnoth639c9212014-12-11 10:04:32 -0800203 return;
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -0800204#define X(str, tag) \
205 Str << "|" << Name << "|" str "|" << Stats[CS_##tag] << "\n";
206 CODESTATS_TABLE
207#undef X
208 Str << "|" << Name << "|Spills+Fills|"
209 << Stats[CS_NumSpills] + Stats[CS_NumFills] << "\n";
Jim Stichnoth639c9212014-12-11 10:04:32 -0800210 Str << "|" << Name << "|Memory Usage|";
211 if (ssize_t MemUsed = llvm::TimeRecord::getCurrentTime(false).getMemUsed())
212 Str << MemUsed;
213 else
214 Str << "(requires '-track-memory')";
215 Str << "\n";
216}
217
Karl Schimpf2f67b922015-04-22 15:20:16 -0700218GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
Jan Voung1f47ad02015-03-20 15:01:26 -0700219 ELFStreamer *ELFStr, const ClFlags &Flags)
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800220 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
Karl Schimpf2f67b922015-04-22 15:20:16 -0700221 StrEmit(OsEmit), StrError(OsError), Flags(Flags),
222 RNG(Flags.getRandomSeed()), ObjectWriter(),
Jim Stichnothbbca7542015-02-11 16:08:31 -0800223 OptQ(/*Sequential=*/Flags.isSequential(),
224 /*MaxSize=*/Flags.getNumTranslationThreads()),
225 // EmitQ is allowed unlimited size.
John Porto8b1a7052015-06-17 13:20:08 -0700226 EmitQ(/*Sequential=*/Flags.isSequential()),
John Porto1bec8bc2015-06-22 10:51:13 -0700227 DataLowering(TargetDataLowering::createLowering(this)) {
Karl Schimpf2f67b922015-04-22 15:20:16 -0700228 assert(OsDump && "OsDump is not defined for GlobalContext");
229 assert(OsEmit && "OsEmit is not defined for GlobalContext");
230 assert(OsError && "OsError is not defined for GlobalContext");
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800231 // Make sure thread_local fields are properly initialized before any
232 // accesses are made. Do this here instead of at the start of
233 // main() so that all clients (e.g. unit tests) can benefit for
234 // free.
235 GlobalContext::TlsInit();
236 Cfg::TlsInit();
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800237 // Create a new ThreadContext for the current thread. No need to
238 // lock AllThreadContexts at this point since no other threads have
239 // access yet to this GlobalContext object.
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800240 ThreadContext *MyTLS = new ThreadContext();
241 AllThreadContexts.push_back(MyTLS);
242 ICE_TLS_SET_FIELD(TLS, MyTLS);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700243 // Pre-register built-in stack names.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700244 if (BuildDefs::dump()) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800245 // TODO(stichnot): There needs to be a strong relationship between
246 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800247 newTimerStackID("Total across all functions");
248 newTimerStackID("Per-function summary");
249 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800250 Timers.initInto(MyTLS->Timers);
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800251 switch (Flags.getOutFileType()) {
252 case FT_Elf:
Jan Voung08c3bcd2014-12-01 17:55:16 -0800253 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800254 break;
255 case FT_Asm:
256 case FT_Iasm:
257 break;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800258 }
John Porto1bec8bc2015-06-22 10:51:13 -0700259
260 // ProfileBlockInfoVarDecl is initialized here because it takes this as a
261 // parameter -- we want to
262 // ensure that at least this' member variables are initialized.
263 ProfileBlockInfoVarDecl = VariableDeclaration::create(this);
John Porto8b1a7052015-06-17 13:20:08 -0700264 ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
265 ProfileBlockInfoVarDecl->setIsConstant(true);
266
267 // Note: if you change this symbol, make sure to update
268 // runtime/szrt_profiler.c as well.
269 ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info");
270 ProfileBlockInfoVarDecl->setSuppressMangling();
271 ProfileBlockInfoVarDecl->setLinkage(llvm::GlobalValue::ExternalLinkage);
Qining Lu253dc8a2015-06-22 10:10:23 -0700272
273 // Initialize the randomization cookie for constant blinding only if constant
274 // blinding or pooling is turned on.
275 // TODO(stichnot): Using RNG for constant blinding will affect the random
276 // number to be used in nop-insertion and randomize-regalloc.
277 if (Flags.getRandomizeAndPoolImmediatesOption() != RPI_None)
278 RandomizationCookie =
279 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max + 1);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700280}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700281
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800282void GlobalContext::translateFunctions() {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800283 while (std::unique_ptr<Cfg> Func = optQueueBlockingPop()) {
Jim Stichnoth8e928382015-02-02 17:03:08 -0800284 // Install Func in TLS for Cfg-specific container allocators.
285 Cfg::setCurrentCfg(Func.get());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800286 // Reset per-function stats being accumulated in TLS.
287 resetStats();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800288 // Set verbose level to none if the current function does NOT
289 // match the -verbose-focus command-line option.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800290 if (!matchSymbolName(Func->getFunctionName(),
291 getFlags().getVerboseFocusOn()))
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800292 Func->setVerbose(IceV_None);
293 // Disable translation if -notranslate is specified, or if the
294 // current function matches the -translate-only option. If
295 // translation is disabled, just dump the high-level IR and
296 // continue.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800297 if (getFlags().getDisableTranslation() ||
298 !matchSymbolName(Func->getFunctionName(),
299 getFlags().getTranslateOnly())) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800300 Func->dump();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800301 Cfg::setCurrentCfg(nullptr);
302 continue; // Func goes out of scope and gets deleted
303 }
John Portof8b4cc82015-06-09 18:06:19 -0700304
Jim Stichnothbbca7542015-02-11 16:08:31 -0800305 Func->translate();
306 EmitterWorkItem *Item = nullptr;
307 if (Func->hasError()) {
308 getErrorStatus()->assign(EC_Translation);
309 OstreamLocker L(this);
Karl Schimpf2f67b922015-04-22 15:20:16 -0700310 getStrError() << "ICE translation error: " << Func->getFunctionName()
311 << ": " << Func->getError() << "\n";
Jim Stichnothbbca7542015-02-11 16:08:31 -0800312 Item = new EmitterWorkItem(Func->getSequenceNumber());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800313 } else {
Jim Stichnoth24824e72015-02-12 21:35:34 -0800314 Func->getAssembler<>()->setInternal(Func->getInternal());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800315 switch (getFlags().getOutFileType()) {
316 case FT_Elf:
317 case FT_Iasm: {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800318 Func->emitIAS();
319 // The Cfg has already emitted into the assembly buffer, so
320 // stats have been fully collected into this thread's TLS.
321 // Dump them before TLS is reset for the next Cfg.
322 dumpStats(Func->getFunctionName());
323 Assembler *Asm = Func->releaseAssembler();
324 // Copy relevant fields into Asm before Func is deleted.
325 Asm->setFunctionName(Func->getFunctionName());
Jim Stichnothbbca7542015-02-11 16:08:31 -0800326 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm);
John Portof8b4cc82015-06-09 18:06:19 -0700327 Item->setGlobalInits(Func->getGlobalInits());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800328 } break;
329 case FT_Asm:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800330 // The Cfg has not been emitted yet, so stats are not ready
331 // to be dumped.
John Portof8b4cc82015-06-09 18:06:19 -0700332 std::unique_ptr<VariableDeclarationList> GlobalInits =
333 Func->getGlobalInits();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800334 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release());
John Portof8b4cc82015-06-09 18:06:19 -0700335 Item->setGlobalInits(std::move(GlobalInits));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800336 break;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800337 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800338 }
Jim Stichnoth8e928382015-02-02 17:03:08 -0800339 Cfg::setCurrentCfg(nullptr);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800340 assert(Item);
341 emitQueueBlockingPush(Item);
Jim Stichnoth8e928382015-02-02 17:03:08 -0800342 // The Cfg now gets deleted as Func goes out of scope.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800343 }
344}
345
Jim Stichnothbbca7542015-02-11 16:08:31 -0800346namespace {
347
John Porto8b1a7052015-06-17 13:20:08 -0700348void addBlockInfoPtrs(const VariableDeclarationList &Globals,
349 VariableDeclaration *ProfileBlockInfo) {
John Portof8b4cc82015-06-09 18:06:19 -0700350 for (const VariableDeclaration *Global : Globals) {
351 if (Cfg::isProfileGlobal(*Global)) {
352 constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
John Porto8b1a7052015-06-17 13:20:08 -0700353 ProfileBlockInfo->addInitializer(
John Porto1bec8bc2015-06-22 10:51:13 -0700354 VariableDeclaration::RelocInitializer::create(
John Porto8b1a7052015-06-17 13:20:08 -0700355 Global, BlockExecutionCounterOffset));
John Portof8b4cc82015-06-09 18:06:19 -0700356 }
357 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800358}
359
360// Ensure Pending is large enough that Pending[Index] is valid.
361void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) {
362 if (Index >= Pending.size())
363 Pending.resize(Index + 1);
364}
365
366} // end of anonymous namespace
367
Jan Voungfb792842015-06-11 15:27:50 -0700368void GlobalContext::emitFileHeader() {
369 TimerMarker T1(Ice::TimerStack::TT_emit, this);
370 if (getFlags().getOutFileType() == FT_Elf) {
371 getObjectWriter()->writeInitialELFHeader();
372 } else {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700373 if (!BuildDefs::dump()) {
Jim Stichnothc8799682015-06-22 13:04:10 -0700374 getStrError() << "emitFileHeader for non-ELF";
375 getErrorStatus()->assign(EC_Translation);
376 }
Jan Voungfb792842015-06-11 15:27:50 -0700377 TargetHeaderLowering::createLowering(this)->lower();
378 }
379}
380
Jim Stichnothcac003e2015-06-18 12:48:58 -0700381void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
John Porto8b1a7052015-06-17 13:20:08 -0700382
383void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
384 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700385 const bool DumpGlobalVariables = BuildDefs::dump() && Flags.getVerbose() &&
386 Flags.getVerboseFocusOn().empty();
John Porto8b1a7052015-06-17 13:20:08 -0700387 if (DumpGlobalVariables) {
388 OstreamLocker L(this);
389 Ostream &Stream = getStrDump();
390 for (const Ice::VariableDeclaration *Global : Globals) {
391 Global->dump(this, Stream);
392 }
393 }
394 if (Flags.getDisableTranslation())
395 return;
396
John Porto1bec8bc2015-06-22 10:51:13 -0700397 addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl);
John Porto8b1a7052015-06-17 13:20:08 -0700398 DataLowering->lowerGlobals(Globals, SectionSuffix);
John Porto1bec8bc2015-06-22 10:51:13 -0700399 for (VariableDeclaration *Var : Globals) {
400 Var->discardInitializers();
401 }
John Porto8b1a7052015-06-17 13:20:08 -0700402 Globals.clear();
403}
404
405void GlobalContext::lowerProfileData() {
John Porto1bec8bc2015-06-22 10:51:13 -0700406 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only
407 // ever be nullptr after this method completes. This assertion is a convoluted
408 // way of ensuring lowerProfileData is invoked a single time.
409 assert(ProfileBlockInfoVarDecl != nullptr);
John Porto8b1a7052015-06-17 13:20:08 -0700410 // This adds a 64-bit sentinel entry to the end of our array. For 32-bit
411 // architectures this will waste 4 bytes.
412 const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
413 ProfileBlockInfoVarDecl->addInitializer(
John Porto1bec8bc2015-06-22 10:51:13 -0700414 VariableDeclaration::ZeroInitializer::create(Sizeof64BitNullPtr));
415 Globals.push_back(ProfileBlockInfoVarDecl);
John Porto8b1a7052015-06-17 13:20:08 -0700416 constexpr char ProfileDataSection[] = "$sz_profiler$";
417 lowerGlobals(ProfileDataSection);
John Porto1bec8bc2015-06-22 10:51:13 -0700418 ProfileBlockInfoVarDecl = nullptr;
John Porto8b1a7052015-06-17 13:20:08 -0700419}
420
Jim Stichnothbbca7542015-02-11 16:08:31 -0800421void GlobalContext::emitItems() {
422 const bool Threaded = !getFlags().isSequential();
423 // Pending is a vector containing the reassembled, ordered list of
424 // work items. When we're ready for the next item, we first check
425 // whether it's in the Pending list. If not, we take an item from
426 // the work queue, and if it's not the item we're waiting for, we
427 // insert it into Pending and repeat. The work item is deleted
428 // after it is processed.
429 std::vector<EmitterWorkItem *> Pending;
430 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
431 while (true) {
432 resizePending(Pending, DesiredSequenceNumber);
433 // See if Pending contains DesiredSequenceNumber.
434 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber];
435 if (RawItem == nullptr)
436 RawItem = emitQueueBlockingPop();
437 if (RawItem == nullptr)
John Portof8b4cc82015-06-09 18:06:19 -0700438 break;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800439 uint32_t ItemSeq = RawItem->getSequenceNumber();
440 if (Threaded && ItemSeq != DesiredSequenceNumber) {
441 resizePending(Pending, ItemSeq);
442 Pending[ItemSeq] = RawItem;
443 continue;
444 }
445
446 std::unique_ptr<EmitterWorkItem> Item(RawItem);
447 ++DesiredSequenceNumber;
448 switch (Item->getKind()) {
449 case EmitterWorkItem::WI_Nop:
450 break;
451 case EmitterWorkItem::WI_GlobalInits: {
John Porto8b1a7052015-06-17 13:20:08 -0700452 accumulateGlobals(Item->getGlobalInits());
Jim Stichnothbbca7542015-02-11 16:08:31 -0800453 } break;
454 case EmitterWorkItem::WI_Asm: {
John Porto8b1a7052015-06-17 13:20:08 -0700455 lowerGlobalsIfNoCodeHasBeenSeen();
456 accumulateGlobals(Item->getGlobalInits());
457
Jim Stichnothbbca7542015-02-11 16:08:31 -0800458 std::unique_ptr<Assembler> Asm = Item->getAsm();
459 Asm->alignFunction();
460 IceString MangledName = mangleName(Asm->getFunctionName());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800461 switch (getFlags().getOutFileType()) {
462 case FT_Elf:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800463 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(),
464 Asm.get());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800465 break;
466 case FT_Iasm: {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800467 OstreamLocker L(this);
468 Cfg::emitTextHeader(MangledName, this, Asm.get());
469 Asm->emitIASBytes(this);
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800470 } break;
471 case FT_Asm:
472 llvm::report_fatal_error("Unexpected FT_Asm");
473 break;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800474 }
475 } break;
476 case EmitterWorkItem::WI_Cfg: {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700477 if (!BuildDefs::dump())
Jim Stichnothbbca7542015-02-11 16:08:31 -0800478 llvm::report_fatal_error("WI_Cfg work item created inappropriately");
John Porto8b1a7052015-06-17 13:20:08 -0700479 lowerGlobalsIfNoCodeHasBeenSeen();
480 accumulateGlobals(Item->getGlobalInits());
John Portof8b4cc82015-06-09 18:06:19 -0700481
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800482 assert(getFlags().getOutFileType() == FT_Asm);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800483 std::unique_ptr<Cfg> Func = Item->getCfg();
484 // Unfortunately, we have to temporarily install the Cfg in TLS
485 // because Variable::asType() uses the allocator to create the
486 // differently-typed copy.
487 Cfg::setCurrentCfg(Func.get());
488 Func->emit();
489 Cfg::setCurrentCfg(nullptr);
490 dumpStats(Func->getFunctionName());
491 } break;
492 }
493 }
John Portof8b4cc82015-06-09 18:06:19 -0700494
John Porto8b1a7052015-06-17 13:20:08 -0700495 // In case there are no code to be generated, we invoke the conditional
496 // lowerGlobals again -- this is a no-op if code has been emitted.
497 lowerGlobalsIfNoCodeHasBeenSeen();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800498}
499
Jim Stichnoth217dc082014-07-11 14:06:55 -0700500// Scan a string for S[0-9A-Z]*_ patterns and replace them with
501// S<num>_ where <num> is the next base-36 value. If a type name
502// legitimately contains that pattern, then the substitution will be
503// made in error and most likely the link will fail. In this case,
504// the test classes can be rewritten not to use that pattern, which is
505// much simpler and more reliable than implementing a full demangling
506// parser. Another substitution-in-error may occur if a type
507// identifier ends with the pattern S[0-9A-Z]*, because an immediately
508// following substitution string like "S1_" or "PS1_" may be combined
509// with the previous type.
510void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const {
511 const std::locale CLocale("C");
512 // Provide extra space in case the length of <num> increases.
513 ManglerVector NewName(OldName.size() * 2);
514 size_t OldPos = 0;
515 size_t NewPos = 0;
516 size_t OldLen = OldName.size();
517 for (; OldPos < OldLen; ++OldPos, ++NewPos) {
518 if (OldName[OldPos] == '\0')
519 break;
520 if (OldName[OldPos] == 'S') {
521 // Search forward until we find _ or invalid character (including \0).
522 bool AllZs = true;
523 bool Found = false;
524 size_t Last;
525 for (Last = OldPos + 1; Last < OldLen; ++Last) {
526 char Ch = OldName[Last];
527 if (Ch == '_') {
528 Found = true;
529 break;
530 } else if (std::isdigit(Ch) || std::isupper(Ch, CLocale)) {
531 if (Ch != 'Z')
532 AllZs = false;
533 } else {
534 // Invalid character, stop searching.
535 break;
536 }
537 }
538 if (Found) {
539 NewName[NewPos++] = OldName[OldPos++]; // 'S'
540 size_t Length = Last - OldPos;
541 // NewPos and OldPos point just past the 'S'.
542 assert(NewName[NewPos - 1] == 'S');
543 assert(OldName[OldPos - 1] == 'S');
544 assert(OldName[OldPos + Length] == '_');
545 if (AllZs) {
Jim Stichnoth78b4c0b2014-07-11 15:29:23 -0700546 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if
547 // N>0) followed by N '0' characters.
548 NewName[NewPos++] = (Length ? '1' : '0');
549 for (size_t i = 0; i < Length; ++i) {
Jim Stichnoth217dc082014-07-11 14:06:55 -0700550 NewName[NewPos++] = '0';
551 }
552 } else {
553 // Iterate right-to-left and increment the base-36 number.
554 bool Carry = true;
555 for (size_t i = 0; i < Length; ++i) {
556 size_t Offset = Length - 1 - i;
557 char Ch = OldName[OldPos + Offset];
558 if (Carry) {
559 Carry = false;
560 switch (Ch) {
561 case '9':
562 Ch = 'A';
563 break;
564 case 'Z':
565 Ch = '0';
566 Carry = true;
567 break;
568 default:
569 ++Ch;
570 break;
571 }
572 }
573 NewName[NewPos + Offset] = Ch;
574 }
575 NewPos += Length;
576 }
577 OldPos = Last;
578 // Fall through and let the '_' be copied across.
579 }
580 }
581 NewName[NewPos] = OldName[OldPos];
582 }
583 assert(NewName[NewPos] == '\0');
584 OldName = NewName;
585}
586
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700587// In this context, name mangling means to rewrite a symbol using a
588// given prefix. For a C++ symbol, nest the original symbol inside
589// the "prefix" namespace. For other symbols, just prepend the
590// prefix.
591IceString GlobalContext::mangleName(const IceString &Name) const {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700592 // An already-nested name like foo::bar() gets pushed down one
593 // level, making it equivalent to Prefix::foo::bar().
594 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
595 // A non-nested but mangled name like bar() gets nested, making it
596 // equivalent to Prefix::bar().
597 // _Z3barxyz ==> ZN6Prefix3barExyz
598 // An unmangled, extern "C" style name, gets a simple prefix:
599 // bar ==> Prefixbar
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700600 if (!BuildDefs::dump() || getFlags().getTestPrefix().empty())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700601 return Name;
602
Jan Voung1f47ad02015-03-20 15:01:26 -0700603 const IceString &TestPrefix = getFlags().getTestPrefix();
604 unsigned PrefixLength = TestPrefix.length();
Jim Stichnoth217dc082014-07-11 14:06:55 -0700605 ManglerVector NameBase(1 + Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700606 const size_t BufLen = 30 + Name.length() + PrefixLength;
Jim Stichnoth217dc082014-07-11 14:06:55 -0700607 ManglerVector NewName(BufLen);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700608 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700609
Derek Schuff44712d12014-06-17 14:34:34 -0700610 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700611 if (ItemsParsed == 1) {
612 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
613 // (splice in "6Prefix") ^^^^^^^
Derek Schuff44712d12014-06-17 14:34:34 -0700614 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
Jan Voung1f47ad02015-03-20 15:01:26 -0700615 TestPrefix.c_str(), NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700616 // We ignore the snprintf return value (here and below). If we
617 // somehow miscalculated the output buffer length, the output will
618 // be truncated, but it will be truncated consistently for all
619 // mangleName() calls on the same input string.
Jim Stichnoth217dc082014-07-11 14:06:55 -0700620 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700621 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700622 }
623
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700624 // Artificially limit BaseLength to 9 digits (less than 1 billion)
625 // because sscanf behavior is undefined on integer overflow. If
626 // there are more than 9 digits (which we test by looking at the
627 // beginning of NameBase), then we consider this a failure to parse
628 // a namespace mangling, and fall back to the simple prefixing.
Derek Schuff44712d12014-06-17 14:34:34 -0700629 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data());
630 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) &&
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700631 !isdigit(NameBase[0])) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700632 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz
633 // ^^^^^^^^ ^
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700634 // (splice in "N6Prefix", and insert "E" after "3bar")
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700635 // But an "I" after the identifier indicates a template argument
636 // list terminated with "E"; insert the new "E" before/after the
637 // old "E". E.g.:
638 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz
639 // ^^^^^^^^ ^
640 // (splice in "N6Prefix", and insert "E" after "3barIabcE")
Jim Stichnoth217dc082014-07-11 14:06:55 -0700641 ManglerVector OrigName(Name.length());
642 ManglerVector OrigSuffix(Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700643 uint32_t ActualBaseLength = BaseLength;
644 if (NameBase[ActualBaseLength] == 'I') {
645 ++ActualBaseLength;
646 while (NameBase[ActualBaseLength] != 'E' &&
647 NameBase[ActualBaseLength] != '\0')
648 ++ActualBaseLength;
649 }
Derek Schuff44712d12014-06-17 14:34:34 -0700650 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700651 OrigName[ActualBaseLength] = '\0';
Derek Schuff44712d12014-06-17 14:34:34 -0700652 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
653 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
Jan Voung1f47ad02015-03-20 15:01:26 -0700654 TestPrefix.c_str(), BaseLength, OrigName.data(),
Derek Schuff44712d12014-06-17 14:34:34 -0700655 OrigSuffix.data());
Jim Stichnoth217dc082014-07-11 14:06:55 -0700656 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700657 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700658 }
659
660 // Transform bar ==> Prefixbar
661 // ^^^^^^
Jan Voung1f47ad02015-03-20 15:01:26 -0700662 return TestPrefix + Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700663}
664
Karl Schimpf9d98d792014-10-13 15:01:08 -0700665GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800666 llvm::DeleteContainerPointers(AllThreadContexts);
John Porto1bec8bc2015-06-22 10:51:13 -0700667 LockedPtr<DestructorArray> Dtors = getDestructors();
668 // Destructors are invoked in the opposite object construction order.
669 for (auto DtorIter = Dtors->crbegin(); DtorIter != Dtors->crend();
670 ++DtorIter) {
671 (*DtorIter)();
672 }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700673}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700674
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800675// TODO(stichnot): Consider adding thread-local caches of constant
676// pool entries to reduce contention.
677
678// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800679Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
680 switch (Ty) {
681 case IceType_i1:
682 return getConstantInt1(Value);
683 case IceType_i8:
684 return getConstantInt8(Value);
685 case IceType_i16:
686 return getConstantInt16(Value);
687 case IceType_i32:
688 return getConstantInt32(Value);
689 case IceType_i64:
690 return getConstantInt64(Value);
691 default:
692 llvm_unreachable("Bad integer type for getConstant");
693 }
Jim Stichnothae953202014-12-20 06:17:49 -0800694 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700695}
696
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800697Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
698 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800699 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800700}
701
702Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800703 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800704}
705
706Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800707 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800708}
709
710Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800711 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800712}
713
714Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800715 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700716}
717
718Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800719 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700720}
721
722Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800723 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700724}
725
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800726Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700727 const IceString &Name,
728 bool SuppressMangling) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800729 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800730 this, RelocatableTuple(Offset, Name, SuppressMangling));
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700731}
732
Jan Voung261cae32015-02-01 10:31:03 -0800733Constant *GlobalContext::getConstantExternSym(const IceString &Name) {
734 const RelocOffsetT Offset = 0;
735 const bool SuppressMangling = true;
736 return getConstPool()->ExternRelocatables.getOrAdd(
737 this, RelocatableTuple(Offset, Name, SuppressMangling));
738}
739
Matt Walad8f4a7d2014-06-18 09:55:03 -0700740Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800741 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700742}
743
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800744// All locking is done by the getConstant*() target function.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700745Constant *GlobalContext::getConstantZero(Type Ty) {
746 switch (Ty) {
747 case IceType_i1:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800748 return getConstantInt1(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700749 case IceType_i8:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800750 return getConstantInt8(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700751 case IceType_i16:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800752 return getConstantInt16(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700753 case IceType_i32:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800754 return getConstantInt32(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700755 case IceType_i64:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800756 return getConstantInt64(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700757 case IceType_f32:
758 return getConstantFloat(0);
759 case IceType_f64:
760 return getConstantDouble(0);
Matt Wala928f1292014-07-07 16:50:46 -0700761 case IceType_v4i1:
762 case IceType_v8i1:
763 case IceType_v16i1:
764 case IceType_v16i8:
765 case IceType_v8i16:
766 case IceType_v4i32:
767 case IceType_v4f32: {
768 IceString Str;
769 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700770 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700771 llvm_unreachable(BaseOS.str().c_str());
772 } break;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700773 case IceType_void:
774 case IceType_NUM:
775 break;
776 }
777 llvm_unreachable("Unknown type");
778}
779
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800780ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700781 switch (Ty) {
782 case IceType_i1:
783 case IceType_i8:
Qining Lu253dc8a2015-06-22 10:10:23 -0700784 return getConstPool()->Integers8.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700785 case IceType_i16:
Qining Lu253dc8a2015-06-22 10:10:23 -0700786 return getConstPool()->Integers16.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700787 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800788 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700789 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800790 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700791 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800792 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700793 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800794 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700795 case IceType_v4i1:
796 case IceType_v8i1:
797 case IceType_v16i1:
798 case IceType_v16i8:
799 case IceType_v8i16:
800 case IceType_v4i32:
801 case IceType_v4f32: {
802 IceString Str;
803 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700804 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700805 llvm_unreachable(BaseOS.str().c_str());
806 } break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700807 case IceType_void:
808 case IceType_NUM:
809 break;
810 }
811 llvm_unreachable("Unknown type");
812}
813
Jan Voung261cae32015-02-01 10:31:03 -0800814ConstantList GlobalContext::getConstantExternSyms() {
815 return getConstPool()->ExternRelocatables.getConstantPool();
816}
817
Jim Stichnoth8363a062014-10-07 10:02:38 -0700818TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700819 if (!BuildDefs::dump())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800820 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800821 auto Timers = getTimers();
822 TimerStackIdT NewID = Timers->size();
823 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700824 return NewID;
825}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700826
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800827TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
828 const IceString &Name) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800829 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800830 assert(StackID < Timers->size());
831 return Timers->at(StackID).getTimerID(Name);
832}
833
Jim Stichnoth8363a062014-10-07 10:02:38 -0700834void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800835 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800836 assert(StackID < Timers->size());
837 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700838}
839
840void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800841 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800842 assert(StackID < Timers->size());
843 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700844}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700845
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700846void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800847 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800848 assert(StackID < Timers->size());
849 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700850}
851
852void GlobalContext::setTimerName(TimerStackIdT StackID,
853 const IceString &NewName) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800854 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800855 assert(StackID < Timers->size());
856 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700857}
858
Jim Stichnothbbca7542015-02-11 16:08:31 -0800859// Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr
Jim Stichnoth8e928382015-02-02 17:03:08 -0800860// at the interface to take and transfer ownership, but they
861// internally store the raw Cfg pointer in the work queue. This
862// allows e.g. future queue optimizations such as the use of atomics
863// to modify queue elements.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800864void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) {
865 assert(Func);
866 OptQ.blockingPush(Func.release());
867 if (getFlags().isSequential())
868 translateFunctions();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800869}
870
Jim Stichnothbbca7542015-02-11 16:08:31 -0800871std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() {
872 return std::unique_ptr<Cfg>(OptQ.blockingPop());
873}
874
875void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) {
876 assert(Item);
877 EmitQ.blockingPush(Item);
878 if (getFlags().isSequential())
879 emitItems();
880}
881
882EmitterWorkItem *GlobalContext::emitQueueBlockingPop() {
883 return EmitQ.blockingPop();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800884}
885
Jim Stichnothff9c7062014-09-18 04:50:49 -0700886void GlobalContext::dumpStats(const IceString &Name, bool Final) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800887 if (!getFlags().getDumpStats())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800888 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800889 OstreamLocker OL(this);
890 if (Final) {
891 getStatsCumulative()->dump(Name, getStrDump());
892 } else {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800893 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump());
Jim Stichnoth18735602014-09-16 19:59:35 -0700894 }
895}
896
Jim Stichnoth8363a062014-10-07 10:02:38 -0700897void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700898 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800899 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800900 auto Timers = getTimers();
901 assert(Timers->size() > StackID);
902 OstreamLocker L(this);
903 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700904}
905
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800906void TimerMarker::push() {
907 switch (StackID) {
908 case GlobalContext::TSK_Default:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800909 Active = Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800910 break;
911 case GlobalContext::TSK_Funcs:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800912 Active = Ctx->getFlags().getTimeEachFunction();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800913 break;
914 default:
915 break;
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800916 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800917 if (Active)
918 Ctx->pushTimer(ID, StackID);
919}
920
921void TimerMarker::pushCfg(const Cfg *Func) {
922 Ctx = Func->getContext();
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800923 Active =
924 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800925 if (Active)
926 Ctx->pushTimer(ID, StackID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700927}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700928
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800929ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800930
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700931} // end of namespace Ice