blob: 51ca3f08240d49b4252358ef2c62389b2c0f05de [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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file defines aspects of the compilation that persist across
12/// multiple functions.
13///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070014//===----------------------------------------------------------------------===//
15
John Porto67f8de92015-06-25 10:14:17 -070016#include "IceGlobalContext.h"
Jim Stichnoth639c9212014-12-11 10:04:32 -080017
Jim Stichnothf7c9a142014-04-29 10:52:43 -070018#include "IceCfg.h"
John Portof8b4cc82015-06-09 18:06:19 -070019#include "IceCfgNode.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070020#include "IceClFlags.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070021#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080022#include "IceELFObjectWriter.h"
Karl Schimpf9d98d792014-10-13 15:01:08 -070023#include "IceGlobalInits.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070025#include "IceTargetLowering.h"
Jim Stichnothc4554d72014-09-30 16:49:38 -070026#include "IceTimerTree.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070027#include "IceTypes.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070028
29#pragma clang diagnostic push
30#pragma clang diagnostic ignored "-Wunused-parameter"
John Porto67f8de92015-06-25 10:14:17 -070031#include "llvm/Support/Timer.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070032#pragma clang diagnostic pop
John Porto67f8de92015-06-25 10:14:17 -070033
Qining Lu7cd53512015-06-26 09:36:00 -070034#include <algorithm> // max()
Jan Vounge0df91f2015-06-30 08:47:06 -070035#include <cctype> // isdigit(), isupper()
36#include <locale> // locale
John Porto67f8de92015-06-25 10:14:17 -070037#include <unordered_map>
38
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080039namespace std {
40template <> struct hash<Ice::RelocatableTuple> {
41 size_t operator()(const Ice::RelocatableTuple &Key) const {
42 return hash<Ice::IceString>()(Key.Name) +
43 hash<Ice::RelocOffsetT>()(Key.Offset);
Jim Stichnothd2cb4362014-11-20 11:24:42 -080044 }
45};
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080046} // end of namespace std
Jim Stichnothd2cb4362014-11-20 11:24:42 -080047
Jim Stichnothf7c9a142014-04-29 10:52:43 -070048namespace Ice {
49
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070050namespace {
51
52// Define the key comparison function for the constant pool's
53// unordered_map, but only for key types of interest: integer types,
54// floating point types, and the special RelocatableTuple.
55template <typename KeyType, class Enable = void> struct KeyCompare {};
56
57template <typename KeyType>
58struct KeyCompare<KeyType,
59 typename std::enable_if<
60 std::is_integral<KeyType>::value ||
61 std::is_same<KeyType, RelocatableTuple>::value>::type> {
62 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
63 return Value1 == Value2;
64 }
65};
66template <typename KeyType>
67struct KeyCompare<KeyType, typename std::enable_if<
68 std::is_floating_point<KeyType>::value>::type> {
69 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
70 return !memcmp(&Value1, &Value2, sizeof(KeyType));
71 }
72};
73
Jim Stichnoth6e293c82015-04-09 09:11:18 -070074// Define a key comparison function for sorting the constant pool's
75// values after they are dumped to a vector. This covers integer
76// types, floating point types, and ConstantRelocatable values.
77template <typename ValueType, class Enable = void> struct KeyCompareLess {};
78
79template <typename ValueType>
80struct KeyCompareLess<ValueType,
81 typename std::enable_if<std::is_floating_point<
82 typename ValueType::PrimType>::value>::type> {
83 bool operator()(const Constant *Const1, const Constant *Const2) const {
84 typedef uint64_t CompareType;
85 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType),
86 "Expected floating-point type of width 64-bit or less");
87 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
88 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
89 // We avoid "V1<V2" because of NaN.
90 // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the
91 // endian-ness of the host system running Subzero.
92 // Instead, compare the result of bit_cast to uint64_t.
93 uint64_t I1 = 0, I2 = 0;
94 memcpy(&I1, &V1, sizeof(V1));
95 memcpy(&I2, &V2, sizeof(V2));
96 return I1 < I2;
97 }
98};
99template <typename ValueType>
100struct KeyCompareLess<ValueType,
101 typename std::enable_if<std::is_integral<
102 typename ValueType::PrimType>::value>::type> {
103 bool operator()(const Constant *Const1, const Constant *Const2) const {
104 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
105 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
106 return V1 < V2;
107 }
108};
109template <typename ValueType>
110struct KeyCompareLess<
111 ValueType, typename std::enable_if<
112 std::is_same<ValueType, ConstantRelocatable>::value>::type> {
113 bool operator()(const Constant *Const1, const Constant *Const2) const {
114 auto V1 = llvm::cast<ValueType>(Const1);
115 auto V2 = llvm::cast<ValueType>(Const2);
116 if (V1->getName() == V2->getName())
117 return V1->getOffset() < V2->getOffset();
118 return V1->getName() < V2->getName();
119 }
120};
121
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700122// TypePool maps constants of type KeyType (e.g. float) to pointers to
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800123// type ValueType (e.g. ConstantFloat).
124template <Type Ty, typename KeyType, typename ValueType> class TypePool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700125 TypePool(const TypePool &) = delete;
126 TypePool &operator=(const TypePool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700127
128public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700129 TypePool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800130 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
131 auto Iter = Pool.find(Key);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700132 if (Iter != Pool.end())
133 return Iter->second;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700134 ValueType *Result = ValueType::create(Ctx, Ty, Key, NextPoolID++);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800135 Pool[Key] = Result;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700136 return Result;
137 }
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700138 ConstantList getConstantPool() const {
139 ConstantList Constants;
140 Constants.reserve(Pool.size());
Jim Stichnothf44f3712014-10-01 14:05:51 -0700141 for (auto &I : Pool)
142 Constants.push_back(I.second);
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700143 // The sort (and its KeyCompareLess machinery) is not strictly
144 // necessary, but is desirable for producing output that is
145 // deterministic across unordered_map::iterator implementations.
146 std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>());
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700147 return Constants;
148 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700149
150private:
Jim Stichnoth5bfe2152015-03-19 13:51:56 -0700151 // Use the default hash function, and a custom key comparison
152 // function. The key comparison function for floating point
153 // variables can't use the default == based implementation because
154 // of special C++ semantics regarding +0.0, -0.0, and NaN
155 // comparison. However, it's OK to use the default hash for
156 // floating point values because KeyCompare is the final source of
157 // truth - in the worst case a "false" collision must be resolved.
158 typedef std::unordered_map<KeyType, ValueType *, std::hash<KeyType>,
159 KeyCompare<KeyType>> ContainerType;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700160 ContainerType Pool;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700161 uint32_t NextPoolID = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700162};
163
Matt Walad8f4a7d2014-06-18 09:55:03 -0700164// UndefPool maps ICE types to the corresponding ConstantUndef values.
165class UndefPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700166 UndefPool(const UndefPool &) = delete;
167 UndefPool &operator=(const UndefPool &) = delete;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700168
169public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700170 UndefPool() : Pool(IceType_NUM) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700171
172 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
Jim Stichnothae953202014-12-20 06:17:49 -0800173 if (Pool[Ty] == nullptr)
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800174 Pool[Ty] = ConstantUndef::create(Ctx, Ty, NextPoolID++);
175 return Pool[Ty];
Matt Walad8f4a7d2014-06-18 09:55:03 -0700176 }
177
178private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700179 uint32_t NextPoolID = 0;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800180 std::vector<ConstantUndef *> Pool;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700181};
182
Jim Stichnoth5bfe2152015-03-19 13:51:56 -0700183} // end of anonymous namespace
184
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700185// The global constant pool bundles individual pools of each type of
186// interest.
187class ConstantPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700188 ConstantPool(const ConstantPool &) = delete;
189 ConstantPool &operator=(const ConstantPool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700190
191public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700192 ConstantPool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800193 TypePool<IceType_f32, float, ConstantFloat> Floats;
194 TypePool<IceType_f64, double, ConstantDouble> Doubles;
195 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
196 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
197 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
198 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
199 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
200 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
Jan Voung261cae32015-02-01 10:31:03 -0800201 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable>
202 ExternRelocatables;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700203 UndefPool Undefs;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700204};
205
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800206void GlobalContext::CodeStats::dump(const IceString &Name, Ostream &Str) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700207 if (!BuildDefs::dump())
Jim Stichnoth639c9212014-12-11 10:04:32 -0800208 return;
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -0800209#define X(str, tag) \
210 Str << "|" << Name << "|" str "|" << Stats[CS_##tag] << "\n";
211 CODESTATS_TABLE
212#undef X
213 Str << "|" << Name << "|Spills+Fills|"
214 << Stats[CS_NumSpills] + Stats[CS_NumFills] << "\n";
Jim Stichnoth639c9212014-12-11 10:04:32 -0800215 Str << "|" << Name << "|Memory Usage|";
216 if (ssize_t MemUsed = llvm::TimeRecord::getCurrentTime(false).getMemUsed())
217 Str << MemUsed;
218 else
219 Str << "(requires '-track-memory')";
220 Str << "\n";
221}
222
Karl Schimpf2f67b922015-04-22 15:20:16 -0700223GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
Jan Voung1f47ad02015-03-20 15:01:26 -0700224 ELFStreamer *ELFStr, const ClFlags &Flags)
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800225 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
Karl Schimpf2f67b922015-04-22 15:20:16 -0700226 StrEmit(OsEmit), StrError(OsError), Flags(Flags),
227 RNG(Flags.getRandomSeed()), ObjectWriter(),
Jim Stichnothbbca7542015-02-11 16:08:31 -0800228 OptQ(/*Sequential=*/Flags.isSequential(),
229 /*MaxSize=*/Flags.getNumTranslationThreads()),
230 // EmitQ is allowed unlimited size.
John Porto8b1a7052015-06-17 13:20:08 -0700231 EmitQ(/*Sequential=*/Flags.isSequential()),
John Porto1bec8bc2015-06-22 10:51:13 -0700232 DataLowering(TargetDataLowering::createLowering(this)) {
Karl Schimpf2f67b922015-04-22 15:20:16 -0700233 assert(OsDump && "OsDump is not defined for GlobalContext");
234 assert(OsEmit && "OsEmit is not defined for GlobalContext");
235 assert(OsError && "OsError is not defined for GlobalContext");
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800236 // Make sure thread_local fields are properly initialized before any
237 // accesses are made. Do this here instead of at the start of
238 // main() so that all clients (e.g. unit tests) can benefit for
239 // free.
240 GlobalContext::TlsInit();
241 Cfg::TlsInit();
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800242 // Create a new ThreadContext for the current thread. No need to
243 // lock AllThreadContexts at this point since no other threads have
244 // access yet to this GlobalContext object.
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800245 ThreadContext *MyTLS = new ThreadContext();
246 AllThreadContexts.push_back(MyTLS);
247 ICE_TLS_SET_FIELD(TLS, MyTLS);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700248 // Pre-register built-in stack names.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700249 if (BuildDefs::dump()) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800250 // TODO(stichnot): There needs to be a strong relationship between
251 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800252 newTimerStackID("Total across all functions");
253 newTimerStackID("Per-function summary");
254 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800255 Timers.initInto(MyTLS->Timers);
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800256 switch (Flags.getOutFileType()) {
257 case FT_Elf:
Jan Voung08c3bcd2014-12-01 17:55:16 -0800258 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800259 break;
260 case FT_Asm:
261 case FT_Iasm:
262 break;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800263 }
John Porto1bec8bc2015-06-22 10:51:13 -0700264
265 // ProfileBlockInfoVarDecl is initialized here because it takes this as a
266 // parameter -- we want to
267 // ensure that at least this' member variables are initialized.
268 ProfileBlockInfoVarDecl = VariableDeclaration::create(this);
John Porto8b1a7052015-06-17 13:20:08 -0700269 ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
270 ProfileBlockInfoVarDecl->setIsConstant(true);
271
272 // Note: if you change this symbol, make sure to update
273 // runtime/szrt_profiler.c as well.
274 ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info");
275 ProfileBlockInfoVarDecl->setSuppressMangling();
276 ProfileBlockInfoVarDecl->setLinkage(llvm::GlobalValue::ExternalLinkage);
Qining Lu253dc8a2015-06-22 10:10:23 -0700277
278 // Initialize the randomization cookie for constant blinding only if constant
279 // blinding or pooling is turned on.
280 // TODO(stichnot): Using RNG for constant blinding will affect the random
281 // number to be used in nop-insertion and randomize-regalloc.
282 if (Flags.getRandomizeAndPoolImmediatesOption() != RPI_None)
283 RandomizationCookie =
284 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max + 1);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700285}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700286
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800287void GlobalContext::translateFunctions() {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800288 while (std::unique_ptr<Cfg> Func = optQueueBlockingPop()) {
Jim Stichnoth8e928382015-02-02 17:03:08 -0800289 // Install Func in TLS for Cfg-specific container allocators.
290 Cfg::setCurrentCfg(Func.get());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800291 // Reset per-function stats being accumulated in TLS.
292 resetStats();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800293 // Set verbose level to none if the current function does NOT
294 // match the -verbose-focus command-line option.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800295 if (!matchSymbolName(Func->getFunctionName(),
296 getFlags().getVerboseFocusOn()))
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800297 Func->setVerbose(IceV_None);
298 // Disable translation if -notranslate is specified, or if the
299 // current function matches the -translate-only option. If
300 // translation is disabled, just dump the high-level IR and
301 // continue.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800302 if (getFlags().getDisableTranslation() ||
303 !matchSymbolName(Func->getFunctionName(),
304 getFlags().getTranslateOnly())) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800305 Func->dump();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800306 Cfg::setCurrentCfg(nullptr);
307 continue; // Func goes out of scope and gets deleted
308 }
John Portof8b4cc82015-06-09 18:06:19 -0700309
Jim Stichnothbbca7542015-02-11 16:08:31 -0800310 Func->translate();
311 EmitterWorkItem *Item = nullptr;
312 if (Func->hasError()) {
313 getErrorStatus()->assign(EC_Translation);
314 OstreamLocker L(this);
Karl Schimpf2f67b922015-04-22 15:20:16 -0700315 getStrError() << "ICE translation error: " << Func->getFunctionName()
316 << ": " << Func->getError() << "\n";
Jim Stichnothbbca7542015-02-11 16:08:31 -0800317 Item = new EmitterWorkItem(Func->getSequenceNumber());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800318 } else {
Jim Stichnoth24824e72015-02-12 21:35:34 -0800319 Func->getAssembler<>()->setInternal(Func->getInternal());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800320 switch (getFlags().getOutFileType()) {
321 case FT_Elf:
322 case FT_Iasm: {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800323 Func->emitIAS();
324 // The Cfg has already emitted into the assembly buffer, so
325 // stats have been fully collected into this thread's TLS.
326 // Dump them before TLS is reset for the next Cfg.
327 dumpStats(Func->getFunctionName());
328 Assembler *Asm = Func->releaseAssembler();
329 // Copy relevant fields into Asm before Func is deleted.
330 Asm->setFunctionName(Func->getFunctionName());
Jim Stichnothbbca7542015-02-11 16:08:31 -0800331 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm);
John Portof8b4cc82015-06-09 18:06:19 -0700332 Item->setGlobalInits(Func->getGlobalInits());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800333 } break;
334 case FT_Asm:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800335 // The Cfg has not been emitted yet, so stats are not ready
336 // to be dumped.
John Portof8b4cc82015-06-09 18:06:19 -0700337 std::unique_ptr<VariableDeclarationList> GlobalInits =
338 Func->getGlobalInits();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800339 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release());
John Portof8b4cc82015-06-09 18:06:19 -0700340 Item->setGlobalInits(std::move(GlobalInits));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800341 break;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800342 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800343 }
Jim Stichnoth8e928382015-02-02 17:03:08 -0800344 Cfg::setCurrentCfg(nullptr);
Jim Stichnothbbca7542015-02-11 16:08:31 -0800345 assert(Item);
346 emitQueueBlockingPush(Item);
Jim Stichnoth8e928382015-02-02 17:03:08 -0800347 // The Cfg now gets deleted as Func goes out of scope.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800348 }
349}
350
Jim Stichnothbbca7542015-02-11 16:08:31 -0800351namespace {
352
John Porto8b1a7052015-06-17 13:20:08 -0700353void addBlockInfoPtrs(const VariableDeclarationList &Globals,
354 VariableDeclaration *ProfileBlockInfo) {
John Portof8b4cc82015-06-09 18:06:19 -0700355 for (const VariableDeclaration *Global : Globals) {
356 if (Cfg::isProfileGlobal(*Global)) {
357 constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
John Porto8b1a7052015-06-17 13:20:08 -0700358 ProfileBlockInfo->addInitializer(
John Porto1bec8bc2015-06-22 10:51:13 -0700359 VariableDeclaration::RelocInitializer::create(
John Porto8b1a7052015-06-17 13:20:08 -0700360 Global, BlockExecutionCounterOffset));
John Portof8b4cc82015-06-09 18:06:19 -0700361 }
362 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800363}
364
365// Ensure Pending is large enough that Pending[Index] is valid.
366void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) {
367 if (Index >= Pending.size())
368 Pending.resize(Index + 1);
369}
370
371} // end of anonymous namespace
372
Jan Voungfb792842015-06-11 15:27:50 -0700373void GlobalContext::emitFileHeader() {
374 TimerMarker T1(Ice::TimerStack::TT_emit, this);
375 if (getFlags().getOutFileType() == FT_Elf) {
376 getObjectWriter()->writeInitialELFHeader();
377 } else {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700378 if (!BuildDefs::dump()) {
Jim Stichnothc8799682015-06-22 13:04:10 -0700379 getStrError() << "emitFileHeader for non-ELF";
380 getErrorStatus()->assign(EC_Translation);
381 }
Jan Voungfb792842015-06-11 15:27:50 -0700382 TargetHeaderLowering::createLowering(this)->lower();
383 }
384}
385
Jim Stichnothcac003e2015-06-18 12:48:58 -0700386void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
John Porto8b1a7052015-06-17 13:20:08 -0700387
388void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
389 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700390 const bool DumpGlobalVariables = BuildDefs::dump() && Flags.getVerbose() &&
391 Flags.getVerboseFocusOn().empty();
John Porto8b1a7052015-06-17 13:20:08 -0700392 if (DumpGlobalVariables) {
393 OstreamLocker L(this);
394 Ostream &Stream = getStrDump();
395 for (const Ice::VariableDeclaration *Global : Globals) {
396 Global->dump(this, Stream);
397 }
398 }
399 if (Flags.getDisableTranslation())
400 return;
401
John Porto1bec8bc2015-06-22 10:51:13 -0700402 addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl);
Qining Lu7cd53512015-06-26 09:36:00 -0700403 // If we need to shuffle the layout of global variables, shuffle them now.
404 if (getFlags().shouldReorderGlobalVariables()) {
405 auto *RNGPtr = &RNG;
406 RandomShuffle(Globals.begin(), Globals.end(),
407 [RNGPtr](int N) { return (uint32_t)RNGPtr->next(N); });
408 }
John Porto8b1a7052015-06-17 13:20:08 -0700409 DataLowering->lowerGlobals(Globals, SectionSuffix);
John Porto1bec8bc2015-06-22 10:51:13 -0700410 for (VariableDeclaration *Var : Globals) {
411 Var->discardInitializers();
412 }
John Porto8b1a7052015-06-17 13:20:08 -0700413 Globals.clear();
414}
415
416void GlobalContext::lowerProfileData() {
John Porto1bec8bc2015-06-22 10:51:13 -0700417 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only
418 // ever be nullptr after this method completes. This assertion is a convoluted
419 // way of ensuring lowerProfileData is invoked a single time.
420 assert(ProfileBlockInfoVarDecl != nullptr);
John Porto8b1a7052015-06-17 13:20:08 -0700421 // This adds a 64-bit sentinel entry to the end of our array. For 32-bit
422 // architectures this will waste 4 bytes.
423 const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
424 ProfileBlockInfoVarDecl->addInitializer(
John Porto1bec8bc2015-06-22 10:51:13 -0700425 VariableDeclaration::ZeroInitializer::create(Sizeof64BitNullPtr));
426 Globals.push_back(ProfileBlockInfoVarDecl);
John Porto8b1a7052015-06-17 13:20:08 -0700427 constexpr char ProfileDataSection[] = "$sz_profiler$";
428 lowerGlobals(ProfileDataSection);
John Porto1bec8bc2015-06-22 10:51:13 -0700429 ProfileBlockInfoVarDecl = nullptr;
John Porto8b1a7052015-06-17 13:20:08 -0700430}
431
Jim Stichnothbbca7542015-02-11 16:08:31 -0800432void GlobalContext::emitItems() {
433 const bool Threaded = !getFlags().isSequential();
434 // Pending is a vector containing the reassembled, ordered list of
435 // work items. When we're ready for the next item, we first check
436 // whether it's in the Pending list. If not, we take an item from
437 // the work queue, and if it's not the item we're waiting for, we
438 // insert it into Pending and repeat. The work item is deleted
439 // after it is processed.
440 std::vector<EmitterWorkItem *> Pending;
441 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
Qining Lu7cd53512015-06-26 09:36:00 -0700442 uint32_t ShuffleStartIndex = DesiredSequenceNumber;
443 uint32_t ShuffleEndIndex = DesiredSequenceNumber;
444 bool EmitQueueEmpty = false;
445 const uint32_t ShuffleWindowSize =
446 std::max(1u, getFlags().getReorderFunctionsWindowSize());
447 bool Shuffle = Threaded && getFlags().shouldReorderFunctions();
448 while (!EmitQueueEmpty) {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800449 resizePending(Pending, DesiredSequenceNumber);
450 // See if Pending contains DesiredSequenceNumber.
451 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber];
Qining Lu7cd53512015-06-26 09:36:00 -0700452 if (RawItem == nullptr) {
453 // We need to fetch an EmitterWorkItem from the queue.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800454 RawItem = emitQueueBlockingPop();
Qining Lu7cd53512015-06-26 09:36:00 -0700455 if (RawItem == nullptr) {
456 // This is the notifier for an empty queue.
457 EmitQueueEmpty = true;
458 } else {
459 // We get an EmitterWorkItem, we need to add it to Pending.
460 uint32_t ItemSeq = RawItem->getSequenceNumber();
461 if (Threaded && ItemSeq != DesiredSequenceNumber) {
462 // Not the desired one, add it to Pending but do not increase
463 // DesiredSequenceNumber. Continue the loop, do not emit the item.
464 resizePending(Pending, ItemSeq);
465 Pending[ItemSeq] = RawItem;
466 continue;
467 }
468 // ItemSeq == DesiredSequenceNumber, we need to check if we should
469 // emit it or not. If !Threaded, we're OK with ItemSeq !=
470 // DesiredSequenceNumber.
471 Pending[DesiredSequenceNumber] = RawItem;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800472 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800473 }
Qining Lu7cd53512015-06-26 09:36:00 -0700474 // We have the desired EmitterWorkItem or nullptr as the end notifier.
475 // If the emitter queue is not empty, increase DesiredSequenceNumber and
476 // ShuffleEndIndex.
477 if (!EmitQueueEmpty) {
478 DesiredSequenceNumber++;
479 ShuffleEndIndex++;
480 }
481
482 if (Shuffle) {
483 // Continue fetching EmitterWorkItem if function reordering is turned on,
484 // and emit queue is not empty, and the number of consecutive pending
485 // items is smaller than the window size, and RawItem is not a
486 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid
487 // holding an arbitrarily large GlobalDeclarationList.
488 if (!EmitQueueEmpty &&
489 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize &&
490 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits)
491 continue;
492
493 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to
494 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the
495 // pending items from Pending[ShuffleStartIndex] to
496 // Pending[ShuffleEndIndex].
497 RandomShuffle(Pending.begin() + ShuffleStartIndex,
498 Pending.begin() + ShuffleEndIndex,
499 [this](uint64_t N) { return (uint32_t)RNG.next(N); });
500 }
501
502 // Emit the item from ShuffleStartIndex to ShuffleEndIndex.
503 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
504 std::unique_ptr<EmitterWorkItem> Item(Pending[I]);
505
506 switch (Item->getKind()) {
507 case EmitterWorkItem::WI_Nop:
508 break;
509 case EmitterWorkItem::WI_GlobalInits: {
510 accumulateGlobals(Item->getGlobalInits());
511 } break;
512 case EmitterWorkItem::WI_Asm: {
513 lowerGlobalsIfNoCodeHasBeenSeen();
514 accumulateGlobals(Item->getGlobalInits());
515
516 std::unique_ptr<Assembler> Asm = Item->getAsm();
517 Asm->alignFunction();
518 IceString MangledName = mangleName(Asm->getFunctionName());
519 switch (getFlags().getOutFileType()) {
520 case FT_Elf:
521 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(),
522 Asm.get());
523 break;
524 case FT_Iasm: {
525 OstreamLocker L(this);
526 Cfg::emitTextHeader(MangledName, this, Asm.get());
527 Asm->emitIASBytes(this);
528 } break;
529 case FT_Asm:
530 llvm::report_fatal_error("Unexpected FT_Asm");
531 break;
532 }
533 } break;
534 case EmitterWorkItem::WI_Cfg: {
535 if (!BuildDefs::dump())
536 llvm::report_fatal_error("WI_Cfg work item created inappropriately");
537 lowerGlobalsIfNoCodeHasBeenSeen();
538 accumulateGlobals(Item->getGlobalInits());
539
540 assert(getFlags().getOutFileType() == FT_Asm);
541 std::unique_ptr<Cfg> Func = Item->getCfg();
542 // Unfortunately, we have to temporarily install the Cfg in TLS
543 // because Variable::asType() uses the allocator to create the
544 // differently-typed copy.
545 Cfg::setCurrentCfg(Func.get());
546 Func->emit();
547 Cfg::setCurrentCfg(nullptr);
548 dumpStats(Func->getFunctionName());
549 } break;
550 }
551 }
552 // Update the start index for next shuffling queue
553 ShuffleStartIndex = ShuffleEndIndex;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800554 }
John Portof8b4cc82015-06-09 18:06:19 -0700555
John Porto8b1a7052015-06-17 13:20:08 -0700556 // In case there are no code to be generated, we invoke the conditional
557 // lowerGlobals again -- this is a no-op if code has been emitted.
558 lowerGlobalsIfNoCodeHasBeenSeen();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800559}
560
Jim Stichnoth217dc082014-07-11 14:06:55 -0700561// Scan a string for S[0-9A-Z]*_ patterns and replace them with
562// S<num>_ where <num> is the next base-36 value. If a type name
563// legitimately contains that pattern, then the substitution will be
564// made in error and most likely the link will fail. In this case,
565// the test classes can be rewritten not to use that pattern, which is
566// much simpler and more reliable than implementing a full demangling
567// parser. Another substitution-in-error may occur if a type
568// identifier ends with the pattern S[0-9A-Z]*, because an immediately
569// following substitution string like "S1_" or "PS1_" may be combined
570// with the previous type.
571void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const {
572 const std::locale CLocale("C");
573 // Provide extra space in case the length of <num> increases.
574 ManglerVector NewName(OldName.size() * 2);
575 size_t OldPos = 0;
576 size_t NewPos = 0;
577 size_t OldLen = OldName.size();
578 for (; OldPos < OldLen; ++OldPos, ++NewPos) {
579 if (OldName[OldPos] == '\0')
580 break;
581 if (OldName[OldPos] == 'S') {
582 // Search forward until we find _ or invalid character (including \0).
583 bool AllZs = true;
584 bool Found = false;
585 size_t Last;
586 for (Last = OldPos + 1; Last < OldLen; ++Last) {
587 char Ch = OldName[Last];
588 if (Ch == '_') {
589 Found = true;
590 break;
591 } else if (std::isdigit(Ch) || std::isupper(Ch, CLocale)) {
592 if (Ch != 'Z')
593 AllZs = false;
594 } else {
595 // Invalid character, stop searching.
596 break;
597 }
598 }
599 if (Found) {
600 NewName[NewPos++] = OldName[OldPos++]; // 'S'
601 size_t Length = Last - OldPos;
602 // NewPos and OldPos point just past the 'S'.
603 assert(NewName[NewPos - 1] == 'S');
604 assert(OldName[OldPos - 1] == 'S');
605 assert(OldName[OldPos + Length] == '_');
606 if (AllZs) {
Jim Stichnoth78b4c0b2014-07-11 15:29:23 -0700607 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if
608 // N>0) followed by N '0' characters.
609 NewName[NewPos++] = (Length ? '1' : '0');
610 for (size_t i = 0; i < Length; ++i) {
Jim Stichnoth217dc082014-07-11 14:06:55 -0700611 NewName[NewPos++] = '0';
612 }
613 } else {
614 // Iterate right-to-left and increment the base-36 number.
615 bool Carry = true;
616 for (size_t i = 0; i < Length; ++i) {
617 size_t Offset = Length - 1 - i;
618 char Ch = OldName[OldPos + Offset];
619 if (Carry) {
620 Carry = false;
621 switch (Ch) {
622 case '9':
623 Ch = 'A';
624 break;
625 case 'Z':
626 Ch = '0';
627 Carry = true;
628 break;
629 default:
630 ++Ch;
631 break;
632 }
633 }
634 NewName[NewPos + Offset] = Ch;
635 }
636 NewPos += Length;
637 }
638 OldPos = Last;
639 // Fall through and let the '_' be copied across.
640 }
641 }
642 NewName[NewPos] = OldName[OldPos];
643 }
644 assert(NewName[NewPos] == '\0');
645 OldName = NewName;
646}
647
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700648// In this context, name mangling means to rewrite a symbol using a
649// given prefix. For a C++ symbol, nest the original symbol inside
650// the "prefix" namespace. For other symbols, just prepend the
651// prefix.
652IceString GlobalContext::mangleName(const IceString &Name) const {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700653 // An already-nested name like foo::bar() gets pushed down one
654 // level, making it equivalent to Prefix::foo::bar().
655 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
656 // A non-nested but mangled name like bar() gets nested, making it
657 // equivalent to Prefix::bar().
658 // _Z3barxyz ==> ZN6Prefix3barExyz
659 // An unmangled, extern "C" style name, gets a simple prefix:
660 // bar ==> Prefixbar
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700661 if (!BuildDefs::dump() || getFlags().getTestPrefix().empty())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700662 return Name;
663
Jan Voung1f47ad02015-03-20 15:01:26 -0700664 const IceString &TestPrefix = getFlags().getTestPrefix();
665 unsigned PrefixLength = TestPrefix.length();
Jim Stichnoth217dc082014-07-11 14:06:55 -0700666 ManglerVector NameBase(1 + Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700667 const size_t BufLen = 30 + Name.length() + PrefixLength;
Jim Stichnoth217dc082014-07-11 14:06:55 -0700668 ManglerVector NewName(BufLen);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700669 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700670
Derek Schuff44712d12014-06-17 14:34:34 -0700671 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700672 if (ItemsParsed == 1) {
673 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
674 // (splice in "6Prefix") ^^^^^^^
Derek Schuff44712d12014-06-17 14:34:34 -0700675 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
Jan Voung1f47ad02015-03-20 15:01:26 -0700676 TestPrefix.c_str(), NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700677 // We ignore the snprintf return value (here and below). If we
678 // somehow miscalculated the output buffer length, the output will
679 // be truncated, but it will be truncated consistently for all
680 // mangleName() calls on the same input string.
Jim Stichnoth217dc082014-07-11 14:06:55 -0700681 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700682 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700683 }
684
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700685 // Artificially limit BaseLength to 9 digits (less than 1 billion)
686 // because sscanf behavior is undefined on integer overflow. If
687 // there are more than 9 digits (which we test by looking at the
688 // beginning of NameBase), then we consider this a failure to parse
689 // a namespace mangling, and fall back to the simple prefixing.
Derek Schuff44712d12014-06-17 14:34:34 -0700690 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data());
691 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) &&
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700692 !isdigit(NameBase[0])) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700693 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz
694 // ^^^^^^^^ ^
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700695 // (splice in "N6Prefix", and insert "E" after "3bar")
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700696 // But an "I" after the identifier indicates a template argument
697 // list terminated with "E"; insert the new "E" before/after the
698 // old "E". E.g.:
699 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz
700 // ^^^^^^^^ ^
701 // (splice in "N6Prefix", and insert "E" after "3barIabcE")
Jim Stichnoth217dc082014-07-11 14:06:55 -0700702 ManglerVector OrigName(Name.length());
703 ManglerVector OrigSuffix(Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700704 uint32_t ActualBaseLength = BaseLength;
705 if (NameBase[ActualBaseLength] == 'I') {
706 ++ActualBaseLength;
707 while (NameBase[ActualBaseLength] != 'E' &&
708 NameBase[ActualBaseLength] != '\0')
709 ++ActualBaseLength;
710 }
Derek Schuff44712d12014-06-17 14:34:34 -0700711 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700712 OrigName[ActualBaseLength] = '\0';
Derek Schuff44712d12014-06-17 14:34:34 -0700713 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
714 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
Jan Voung1f47ad02015-03-20 15:01:26 -0700715 TestPrefix.c_str(), BaseLength, OrigName.data(),
Derek Schuff44712d12014-06-17 14:34:34 -0700716 OrigSuffix.data());
Jim Stichnoth217dc082014-07-11 14:06:55 -0700717 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700718 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700719 }
720
721 // Transform bar ==> Prefixbar
722 // ^^^^^^
Jan Voung1f47ad02015-03-20 15:01:26 -0700723 return TestPrefix + Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700724}
725
Karl Schimpf9d98d792014-10-13 15:01:08 -0700726GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800727 llvm::DeleteContainerPointers(AllThreadContexts);
John Porto1bec8bc2015-06-22 10:51:13 -0700728 LockedPtr<DestructorArray> Dtors = getDestructors();
729 // Destructors are invoked in the opposite object construction order.
730 for (auto DtorIter = Dtors->crbegin(); DtorIter != Dtors->crend();
731 ++DtorIter) {
732 (*DtorIter)();
733 }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700734}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700735
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800736// TODO(stichnot): Consider adding thread-local caches of constant
737// pool entries to reduce contention.
738
739// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800740Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
741 switch (Ty) {
742 case IceType_i1:
743 return getConstantInt1(Value);
744 case IceType_i8:
745 return getConstantInt8(Value);
746 case IceType_i16:
747 return getConstantInt16(Value);
748 case IceType_i32:
749 return getConstantInt32(Value);
750 case IceType_i64:
751 return getConstantInt64(Value);
752 default:
753 llvm_unreachable("Bad integer type for getConstant");
754 }
Jim Stichnothae953202014-12-20 06:17:49 -0800755 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700756}
757
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800758Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
759 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800760 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800761}
762
763Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800764 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800765}
766
767Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800768 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800769}
770
771Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800772 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800773}
774
775Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800776 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700777}
778
779Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800780 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700781}
782
783Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800784 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700785}
786
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800787Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700788 const IceString &Name,
789 bool SuppressMangling) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800790 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800791 this, RelocatableTuple(Offset, Name, SuppressMangling));
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700792}
793
Jan Voung261cae32015-02-01 10:31:03 -0800794Constant *GlobalContext::getConstantExternSym(const IceString &Name) {
795 const RelocOffsetT Offset = 0;
796 const bool SuppressMangling = true;
797 return getConstPool()->ExternRelocatables.getOrAdd(
798 this, RelocatableTuple(Offset, Name, SuppressMangling));
799}
800
Matt Walad8f4a7d2014-06-18 09:55:03 -0700801Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800802 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700803}
804
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800805// All locking is done by the getConstant*() target function.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700806Constant *GlobalContext::getConstantZero(Type Ty) {
807 switch (Ty) {
808 case IceType_i1:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800809 return getConstantInt1(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700810 case IceType_i8:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800811 return getConstantInt8(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700812 case IceType_i16:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800813 return getConstantInt16(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700814 case IceType_i32:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800815 return getConstantInt32(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700816 case IceType_i64:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800817 return getConstantInt64(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700818 case IceType_f32:
819 return getConstantFloat(0);
820 case IceType_f64:
821 return getConstantDouble(0);
Matt Wala928f1292014-07-07 16:50:46 -0700822 case IceType_v4i1:
823 case IceType_v8i1:
824 case IceType_v16i1:
825 case IceType_v16i8:
826 case IceType_v8i16:
827 case IceType_v4i32:
828 case IceType_v4f32: {
829 IceString Str;
830 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700831 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700832 llvm_unreachable(BaseOS.str().c_str());
833 } break;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700834 case IceType_void:
835 case IceType_NUM:
836 break;
837 }
838 llvm_unreachable("Unknown type");
839}
840
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800841ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700842 switch (Ty) {
843 case IceType_i1:
844 case IceType_i8:
Qining Lu253dc8a2015-06-22 10:10:23 -0700845 return getConstPool()->Integers8.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700846 case IceType_i16:
Qining Lu253dc8a2015-06-22 10:10:23 -0700847 return getConstPool()->Integers16.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700848 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800849 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700850 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800851 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700852 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800853 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700854 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800855 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700856 case IceType_v4i1:
857 case IceType_v8i1:
858 case IceType_v16i1:
859 case IceType_v16i8:
860 case IceType_v8i16:
861 case IceType_v4i32:
862 case IceType_v4f32: {
863 IceString Str;
864 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700865 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700866 llvm_unreachable(BaseOS.str().c_str());
867 } break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700868 case IceType_void:
869 case IceType_NUM:
870 break;
871 }
872 llvm_unreachable("Unknown type");
873}
874
Jan Voung261cae32015-02-01 10:31:03 -0800875ConstantList GlobalContext::getConstantExternSyms() {
876 return getConstPool()->ExternRelocatables.getConstantPool();
877}
878
Jim Stichnoth8363a062014-10-07 10:02:38 -0700879TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700880 if (!BuildDefs::dump())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800881 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800882 auto Timers = getTimers();
883 TimerStackIdT NewID = Timers->size();
884 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700885 return NewID;
886}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700887
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800888TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
889 const IceString &Name) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800890 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800891 assert(StackID < Timers->size());
892 return Timers->at(StackID).getTimerID(Name);
893}
894
Jim Stichnoth8363a062014-10-07 10:02:38 -0700895void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800896 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800897 assert(StackID < Timers->size());
898 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700899}
900
901void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800902 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800903 assert(StackID < Timers->size());
904 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700905}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700906
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700907void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800908 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800909 assert(StackID < Timers->size());
910 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700911}
912
913void GlobalContext::setTimerName(TimerStackIdT StackID,
914 const IceString &NewName) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800915 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800916 assert(StackID < Timers->size());
917 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700918}
919
Jim Stichnothbbca7542015-02-11 16:08:31 -0800920// Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr
Jim Stichnoth8e928382015-02-02 17:03:08 -0800921// at the interface to take and transfer ownership, but they
922// internally store the raw Cfg pointer in the work queue. This
923// allows e.g. future queue optimizations such as the use of atomics
924// to modify queue elements.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800925void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) {
926 assert(Func);
927 OptQ.blockingPush(Func.release());
928 if (getFlags().isSequential())
929 translateFunctions();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800930}
931
Jim Stichnothbbca7542015-02-11 16:08:31 -0800932std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() {
933 return std::unique_ptr<Cfg>(OptQ.blockingPop());
934}
935
936void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) {
937 assert(Item);
938 EmitQ.blockingPush(Item);
939 if (getFlags().isSequential())
940 emitItems();
941}
942
943EmitterWorkItem *GlobalContext::emitQueueBlockingPop() {
944 return EmitQ.blockingPop();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800945}
946
Jim Stichnothff9c7062014-09-18 04:50:49 -0700947void GlobalContext::dumpStats(const IceString &Name, bool Final) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800948 if (!getFlags().getDumpStats())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800949 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800950 OstreamLocker OL(this);
951 if (Final) {
952 getStatsCumulative()->dump(Name, getStrDump());
953 } else {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800954 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump());
Jim Stichnoth18735602014-09-16 19:59:35 -0700955 }
956}
957
Jim Stichnoth8363a062014-10-07 10:02:38 -0700958void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700959 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800960 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800961 auto Timers = getTimers();
962 assert(Timers->size() > StackID);
963 OstreamLocker L(this);
964 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700965}
966
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800967void TimerMarker::push() {
968 switch (StackID) {
969 case GlobalContext::TSK_Default:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800970 Active = Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800971 break;
972 case GlobalContext::TSK_Funcs:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800973 Active = Ctx->getFlags().getTimeEachFunction();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800974 break;
975 default:
976 break;
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800977 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800978 if (Active)
979 Ctx->pushTimer(ID, StackID);
980}
981
982void TimerMarker::pushCfg(const Cfg *Func) {
983 Ctx = Func->getContext();
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800984 Active =
985 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800986 if (Active)
987 Ctx->pushTimer(ID, StackID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700988}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700989
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800990ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800991
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700992} // end of namespace Ice