blob: 8bfc5dd5022aa126edeedf0b8db9b698f3b8ea1a [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
Andrew Scull86df4e92015-07-30 13:54:44 -0700388void GlobalContext::lowerJumpTables() { DataLowering->lowerJumpTables(); }
389
John Porto8b1a7052015-06-17 13:20:08 -0700390void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
391 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700392 const bool DumpGlobalVariables = BuildDefs::dump() && Flags.getVerbose() &&
393 Flags.getVerboseFocusOn().empty();
John Porto8b1a7052015-06-17 13:20:08 -0700394 if (DumpGlobalVariables) {
395 OstreamLocker L(this);
396 Ostream &Stream = getStrDump();
397 for (const Ice::VariableDeclaration *Global : Globals) {
398 Global->dump(this, Stream);
399 }
400 }
401 if (Flags.getDisableTranslation())
402 return;
403
John Porto1bec8bc2015-06-22 10:51:13 -0700404 addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl);
Qining Lu7cd53512015-06-26 09:36:00 -0700405 // If we need to shuffle the layout of global variables, shuffle them now.
406 if (getFlags().shouldReorderGlobalVariables()) {
407 auto *RNGPtr = &RNG;
408 RandomShuffle(Globals.begin(), Globals.end(),
409 [RNGPtr](int N) { return (uint32_t)RNGPtr->next(N); });
410 }
John Porto8b1a7052015-06-17 13:20:08 -0700411 DataLowering->lowerGlobals(Globals, SectionSuffix);
John Porto1bec8bc2015-06-22 10:51:13 -0700412 for (VariableDeclaration *Var : Globals) {
413 Var->discardInitializers();
414 }
John Porto8b1a7052015-06-17 13:20:08 -0700415 Globals.clear();
416}
417
418void GlobalContext::lowerProfileData() {
John Porto1bec8bc2015-06-22 10:51:13 -0700419 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only
420 // ever be nullptr after this method completes. This assertion is a convoluted
421 // way of ensuring lowerProfileData is invoked a single time.
422 assert(ProfileBlockInfoVarDecl != nullptr);
John Porto8b1a7052015-06-17 13:20:08 -0700423 // This adds a 64-bit sentinel entry to the end of our array. For 32-bit
424 // architectures this will waste 4 bytes.
425 const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
426 ProfileBlockInfoVarDecl->addInitializer(
John Porto1bec8bc2015-06-22 10:51:13 -0700427 VariableDeclaration::ZeroInitializer::create(Sizeof64BitNullPtr));
428 Globals.push_back(ProfileBlockInfoVarDecl);
John Porto8b1a7052015-06-17 13:20:08 -0700429 constexpr char ProfileDataSection[] = "$sz_profiler$";
430 lowerGlobals(ProfileDataSection);
John Porto1bec8bc2015-06-22 10:51:13 -0700431 ProfileBlockInfoVarDecl = nullptr;
John Porto8b1a7052015-06-17 13:20:08 -0700432}
433
Jim Stichnothbbca7542015-02-11 16:08:31 -0800434void GlobalContext::emitItems() {
435 const bool Threaded = !getFlags().isSequential();
436 // Pending is a vector containing the reassembled, ordered list of
437 // work items. When we're ready for the next item, we first check
438 // whether it's in the Pending list. If not, we take an item from
439 // the work queue, and if it's not the item we're waiting for, we
440 // insert it into Pending and repeat. The work item is deleted
441 // after it is processed.
442 std::vector<EmitterWorkItem *> Pending;
443 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
Qining Lu7cd53512015-06-26 09:36:00 -0700444 uint32_t ShuffleStartIndex = DesiredSequenceNumber;
445 uint32_t ShuffleEndIndex = DesiredSequenceNumber;
446 bool EmitQueueEmpty = false;
447 const uint32_t ShuffleWindowSize =
448 std::max(1u, getFlags().getReorderFunctionsWindowSize());
449 bool Shuffle = Threaded && getFlags().shouldReorderFunctions();
450 while (!EmitQueueEmpty) {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800451 resizePending(Pending, DesiredSequenceNumber);
452 // See if Pending contains DesiredSequenceNumber.
453 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber];
Qining Lu7cd53512015-06-26 09:36:00 -0700454 if (RawItem == nullptr) {
455 // We need to fetch an EmitterWorkItem from the queue.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800456 RawItem = emitQueueBlockingPop();
Qining Lu7cd53512015-06-26 09:36:00 -0700457 if (RawItem == nullptr) {
458 // This is the notifier for an empty queue.
459 EmitQueueEmpty = true;
460 } else {
461 // We get an EmitterWorkItem, we need to add it to Pending.
462 uint32_t ItemSeq = RawItem->getSequenceNumber();
463 if (Threaded && ItemSeq != DesiredSequenceNumber) {
464 // Not the desired one, add it to Pending but do not increase
465 // DesiredSequenceNumber. Continue the loop, do not emit the item.
466 resizePending(Pending, ItemSeq);
467 Pending[ItemSeq] = RawItem;
468 continue;
469 }
470 // ItemSeq == DesiredSequenceNumber, we need to check if we should
471 // emit it or not. If !Threaded, we're OK with ItemSeq !=
472 // DesiredSequenceNumber.
473 Pending[DesiredSequenceNumber] = RawItem;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800474 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800475 }
Qining Lu7cd53512015-06-26 09:36:00 -0700476 // We have the desired EmitterWorkItem or nullptr as the end notifier.
477 // If the emitter queue is not empty, increase DesiredSequenceNumber and
478 // ShuffleEndIndex.
479 if (!EmitQueueEmpty) {
480 DesiredSequenceNumber++;
481 ShuffleEndIndex++;
482 }
483
484 if (Shuffle) {
485 // Continue fetching EmitterWorkItem if function reordering is turned on,
486 // and emit queue is not empty, and the number of consecutive pending
487 // items is smaller than the window size, and RawItem is not a
488 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid
489 // holding an arbitrarily large GlobalDeclarationList.
490 if (!EmitQueueEmpty &&
491 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize &&
492 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits)
493 continue;
494
495 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to
496 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the
497 // pending items from Pending[ShuffleStartIndex] to
498 // Pending[ShuffleEndIndex].
499 RandomShuffle(Pending.begin() + ShuffleStartIndex,
500 Pending.begin() + ShuffleEndIndex,
501 [this](uint64_t N) { return (uint32_t)RNG.next(N); });
502 }
503
504 // Emit the item from ShuffleStartIndex to ShuffleEndIndex.
505 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
506 std::unique_ptr<EmitterWorkItem> Item(Pending[I]);
507
508 switch (Item->getKind()) {
509 case EmitterWorkItem::WI_Nop:
510 break;
511 case EmitterWorkItem::WI_GlobalInits: {
512 accumulateGlobals(Item->getGlobalInits());
513 } break;
514 case EmitterWorkItem::WI_Asm: {
515 lowerGlobalsIfNoCodeHasBeenSeen();
516 accumulateGlobals(Item->getGlobalInits());
517
518 std::unique_ptr<Assembler> Asm = Item->getAsm();
519 Asm->alignFunction();
520 IceString MangledName = mangleName(Asm->getFunctionName());
521 switch (getFlags().getOutFileType()) {
522 case FT_Elf:
523 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(),
524 Asm.get());
525 break;
526 case FT_Iasm: {
527 OstreamLocker L(this);
528 Cfg::emitTextHeader(MangledName, this, Asm.get());
529 Asm->emitIASBytes(this);
530 } break;
531 case FT_Asm:
532 llvm::report_fatal_error("Unexpected FT_Asm");
533 break;
534 }
535 } break;
536 case EmitterWorkItem::WI_Cfg: {
537 if (!BuildDefs::dump())
538 llvm::report_fatal_error("WI_Cfg work item created inappropriately");
539 lowerGlobalsIfNoCodeHasBeenSeen();
540 accumulateGlobals(Item->getGlobalInits());
541
542 assert(getFlags().getOutFileType() == FT_Asm);
543 std::unique_ptr<Cfg> Func = Item->getCfg();
544 // Unfortunately, we have to temporarily install the Cfg in TLS
545 // because Variable::asType() uses the allocator to create the
546 // differently-typed copy.
547 Cfg::setCurrentCfg(Func.get());
548 Func->emit();
549 Cfg::setCurrentCfg(nullptr);
550 dumpStats(Func->getFunctionName());
551 } break;
552 }
553 }
554 // Update the start index for next shuffling queue
555 ShuffleStartIndex = ShuffleEndIndex;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800556 }
John Portof8b4cc82015-06-09 18:06:19 -0700557
John Porto8b1a7052015-06-17 13:20:08 -0700558 // In case there are no code to be generated, we invoke the conditional
559 // lowerGlobals again -- this is a no-op if code has been emitted.
560 lowerGlobalsIfNoCodeHasBeenSeen();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800561}
562
Jim Stichnoth217dc082014-07-11 14:06:55 -0700563// Scan a string for S[0-9A-Z]*_ patterns and replace them with
564// S<num>_ where <num> is the next base-36 value. If a type name
565// legitimately contains that pattern, then the substitution will be
566// made in error and most likely the link will fail. In this case,
567// the test classes can be rewritten not to use that pattern, which is
568// much simpler and more reliable than implementing a full demangling
569// parser. Another substitution-in-error may occur if a type
570// identifier ends with the pattern S[0-9A-Z]*, because an immediately
571// following substitution string like "S1_" or "PS1_" may be combined
572// with the previous type.
573void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const {
574 const std::locale CLocale("C");
575 // Provide extra space in case the length of <num> increases.
576 ManglerVector NewName(OldName.size() * 2);
577 size_t OldPos = 0;
578 size_t NewPos = 0;
579 size_t OldLen = OldName.size();
580 for (; OldPos < OldLen; ++OldPos, ++NewPos) {
581 if (OldName[OldPos] == '\0')
582 break;
583 if (OldName[OldPos] == 'S') {
584 // Search forward until we find _ or invalid character (including \0).
585 bool AllZs = true;
586 bool Found = false;
587 size_t Last;
588 for (Last = OldPos + 1; Last < OldLen; ++Last) {
589 char Ch = OldName[Last];
590 if (Ch == '_') {
591 Found = true;
592 break;
593 } else if (std::isdigit(Ch) || std::isupper(Ch, CLocale)) {
594 if (Ch != 'Z')
595 AllZs = false;
596 } else {
597 // Invalid character, stop searching.
598 break;
599 }
600 }
601 if (Found) {
602 NewName[NewPos++] = OldName[OldPos++]; // 'S'
603 size_t Length = Last - OldPos;
604 // NewPos and OldPos point just past the 'S'.
605 assert(NewName[NewPos - 1] == 'S');
606 assert(OldName[OldPos - 1] == 'S');
607 assert(OldName[OldPos + Length] == '_');
608 if (AllZs) {
Jim Stichnoth78b4c0b2014-07-11 15:29:23 -0700609 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if
610 // N>0) followed by N '0' characters.
611 NewName[NewPos++] = (Length ? '1' : '0');
612 for (size_t i = 0; i < Length; ++i) {
Jim Stichnoth217dc082014-07-11 14:06:55 -0700613 NewName[NewPos++] = '0';
614 }
615 } else {
616 // Iterate right-to-left and increment the base-36 number.
617 bool Carry = true;
618 for (size_t i = 0; i < Length; ++i) {
619 size_t Offset = Length - 1 - i;
620 char Ch = OldName[OldPos + Offset];
621 if (Carry) {
622 Carry = false;
623 switch (Ch) {
624 case '9':
625 Ch = 'A';
626 break;
627 case 'Z':
628 Ch = '0';
629 Carry = true;
630 break;
631 default:
632 ++Ch;
633 break;
634 }
635 }
636 NewName[NewPos + Offset] = Ch;
637 }
638 NewPos += Length;
639 }
640 OldPos = Last;
641 // Fall through and let the '_' be copied across.
642 }
643 }
644 NewName[NewPos] = OldName[OldPos];
645 }
646 assert(NewName[NewPos] == '\0');
647 OldName = NewName;
648}
649
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700650// In this context, name mangling means to rewrite a symbol using a
651// given prefix. For a C++ symbol, nest the original symbol inside
652// the "prefix" namespace. For other symbols, just prepend the
653// prefix.
654IceString GlobalContext::mangleName(const IceString &Name) const {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700655 // An already-nested name like foo::bar() gets pushed down one
656 // level, making it equivalent to Prefix::foo::bar().
657 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
658 // A non-nested but mangled name like bar() gets nested, making it
659 // equivalent to Prefix::bar().
660 // _Z3barxyz ==> ZN6Prefix3barExyz
661 // An unmangled, extern "C" style name, gets a simple prefix:
662 // bar ==> Prefixbar
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700663 if (!BuildDefs::dump() || getFlags().getTestPrefix().empty())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700664 return Name;
665
Jan Voung1f47ad02015-03-20 15:01:26 -0700666 const IceString &TestPrefix = getFlags().getTestPrefix();
667 unsigned PrefixLength = TestPrefix.length();
Jim Stichnoth217dc082014-07-11 14:06:55 -0700668 ManglerVector NameBase(1 + Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700669 const size_t BufLen = 30 + Name.length() + PrefixLength;
Jim Stichnoth217dc082014-07-11 14:06:55 -0700670 ManglerVector NewName(BufLen);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700671 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700672
Derek Schuff44712d12014-06-17 14:34:34 -0700673 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700674 if (ItemsParsed == 1) {
675 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
676 // (splice in "6Prefix") ^^^^^^^
Derek Schuff44712d12014-06-17 14:34:34 -0700677 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
Jan Voung1f47ad02015-03-20 15:01:26 -0700678 TestPrefix.c_str(), NameBase.data());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700679 // We ignore the snprintf return value (here and below). If we
680 // somehow miscalculated the output buffer length, the output will
681 // be truncated, but it will be truncated consistently for all
682 // mangleName() calls on the same input string.
Jim Stichnoth217dc082014-07-11 14:06:55 -0700683 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700684 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700685 }
686
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700687 // Artificially limit BaseLength to 9 digits (less than 1 billion)
688 // because sscanf behavior is undefined on integer overflow. If
689 // there are more than 9 digits (which we test by looking at the
690 // beginning of NameBase), then we consider this a failure to parse
691 // a namespace mangling, and fall back to the simple prefixing.
Derek Schuff44712d12014-06-17 14:34:34 -0700692 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data());
693 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) &&
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700694 !isdigit(NameBase[0])) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700695 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz
696 // ^^^^^^^^ ^
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700697 // (splice in "N6Prefix", and insert "E" after "3bar")
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700698 // But an "I" after the identifier indicates a template argument
699 // list terminated with "E"; insert the new "E" before/after the
700 // old "E". E.g.:
701 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz
702 // ^^^^^^^^ ^
703 // (splice in "N6Prefix", and insert "E" after "3barIabcE")
Jim Stichnoth217dc082014-07-11 14:06:55 -0700704 ManglerVector OrigName(Name.length());
705 ManglerVector OrigSuffix(Name.length());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700706 uint32_t ActualBaseLength = BaseLength;
707 if (NameBase[ActualBaseLength] == 'I') {
708 ++ActualBaseLength;
709 while (NameBase[ActualBaseLength] != 'E' &&
710 NameBase[ActualBaseLength] != '\0')
711 ++ActualBaseLength;
712 }
Derek Schuff44712d12014-06-17 14:34:34 -0700713 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700714 OrigName[ActualBaseLength] = '\0';
Derek Schuff44712d12014-06-17 14:34:34 -0700715 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
716 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
Jan Voung1f47ad02015-03-20 15:01:26 -0700717 TestPrefix.c_str(), BaseLength, OrigName.data(),
Derek Schuff44712d12014-06-17 14:34:34 -0700718 OrigSuffix.data());
Jim Stichnoth217dc082014-07-11 14:06:55 -0700719 incrementSubstitutions(NewName);
Derek Schuff44712d12014-06-17 14:34:34 -0700720 return NewName.data();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700721 }
722
723 // Transform bar ==> Prefixbar
724 // ^^^^^^
Jan Voung1f47ad02015-03-20 15:01:26 -0700725 return TestPrefix + Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700726}
727
Karl Schimpf9d98d792014-10-13 15:01:08 -0700728GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800729 llvm::DeleteContainerPointers(AllThreadContexts);
John Porto1bec8bc2015-06-22 10:51:13 -0700730 LockedPtr<DestructorArray> Dtors = getDestructors();
731 // Destructors are invoked in the opposite object construction order.
732 for (auto DtorIter = Dtors->crbegin(); DtorIter != Dtors->crend();
733 ++DtorIter) {
734 (*DtorIter)();
735 }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700736}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700737
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800738// TODO(stichnot): Consider adding thread-local caches of constant
739// pool entries to reduce contention.
740
741// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800742Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
743 switch (Ty) {
744 case IceType_i1:
745 return getConstantInt1(Value);
746 case IceType_i8:
747 return getConstantInt8(Value);
748 case IceType_i16:
749 return getConstantInt16(Value);
750 case IceType_i32:
751 return getConstantInt32(Value);
752 case IceType_i64:
753 return getConstantInt64(Value);
754 default:
755 llvm_unreachable("Bad integer type for getConstant");
756 }
Jim Stichnothae953202014-12-20 06:17:49 -0800757 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700758}
759
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800760Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
761 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800762 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800763}
764
765Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800766 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800767}
768
769Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800770 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800771}
772
773Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800774 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800775}
776
777Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800778 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700779}
780
781Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800782 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700783}
784
785Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800786 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700787}
788
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800789Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700790 const IceString &Name,
791 bool SuppressMangling) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800792 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800793 this, RelocatableTuple(Offset, Name, SuppressMangling));
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700794}
795
Jan Voung261cae32015-02-01 10:31:03 -0800796Constant *GlobalContext::getConstantExternSym(const IceString &Name) {
797 const RelocOffsetT Offset = 0;
798 const bool SuppressMangling = true;
799 return getConstPool()->ExternRelocatables.getOrAdd(
800 this, RelocatableTuple(Offset, Name, SuppressMangling));
801}
802
Matt Walad8f4a7d2014-06-18 09:55:03 -0700803Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800804 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700805}
806
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800807// All locking is done by the getConstant*() target function.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700808Constant *GlobalContext::getConstantZero(Type Ty) {
809 switch (Ty) {
810 case IceType_i1:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800811 return getConstantInt1(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700812 case IceType_i8:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800813 return getConstantInt8(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700814 case IceType_i16:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800815 return getConstantInt16(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700816 case IceType_i32:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800817 return getConstantInt32(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700818 case IceType_i64:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800819 return getConstantInt64(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700820 case IceType_f32:
821 return getConstantFloat(0);
822 case IceType_f64:
823 return getConstantDouble(0);
Matt Wala928f1292014-07-07 16:50:46 -0700824 case IceType_v4i1:
825 case IceType_v8i1:
826 case IceType_v16i1:
827 case IceType_v16i8:
828 case IceType_v8i16:
829 case IceType_v4i32:
830 case IceType_v4f32: {
831 IceString Str;
832 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700833 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700834 llvm_unreachable(BaseOS.str().c_str());
835 } break;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700836 case IceType_void:
837 case IceType_NUM:
838 break;
839 }
840 llvm_unreachable("Unknown type");
841}
842
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800843ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700844 switch (Ty) {
845 case IceType_i1:
846 case IceType_i8:
Qining Lu253dc8a2015-06-22 10:10:23 -0700847 return getConstPool()->Integers8.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700848 case IceType_i16:
Qining Lu253dc8a2015-06-22 10:10:23 -0700849 return getConstPool()->Integers16.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700850 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800851 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700852 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800853 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700854 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800855 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700856 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800857 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700858 case IceType_v4i1:
859 case IceType_v8i1:
860 case IceType_v16i1:
861 case IceType_v16i8:
862 case IceType_v8i16:
863 case IceType_v4i32:
864 case IceType_v4f32: {
865 IceString Str;
866 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700867 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700868 llvm_unreachable(BaseOS.str().c_str());
869 } break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700870 case IceType_void:
871 case IceType_NUM:
872 break;
873 }
874 llvm_unreachable("Unknown type");
875}
876
Jan Voung261cae32015-02-01 10:31:03 -0800877ConstantList GlobalContext::getConstantExternSyms() {
878 return getConstPool()->ExternRelocatables.getConstantPool();
879}
880
Andrew Scull86df4e92015-07-30 13:54:44 -0700881JumpTableData &GlobalContext::addJumpTable(IceString FuncName, SizeT Id,
882 SizeT NumTargets) {
883 auto JumpTables = getJumpTables();
884 JumpTables->emplace_back(FuncName, Id, NumTargets);
885 return JumpTables->back();
886}
887
Jim Stichnoth8363a062014-10-07 10:02:38 -0700888TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700889 if (!BuildDefs::dump())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800890 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800891 auto Timers = getTimers();
892 TimerStackIdT NewID = Timers->size();
893 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700894 return NewID;
895}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700896
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800897TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
898 const IceString &Name) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800899 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800900 assert(StackID < Timers->size());
901 return Timers->at(StackID).getTimerID(Name);
902}
903
Jim Stichnoth8363a062014-10-07 10:02:38 -0700904void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800905 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800906 assert(StackID < Timers->size());
907 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700908}
909
910void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800911 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800912 assert(StackID < Timers->size());
913 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700914}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700915
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700916void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800917 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800918 assert(StackID < Timers->size());
919 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700920}
921
922void GlobalContext::setTimerName(TimerStackIdT StackID,
923 const IceString &NewName) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800924 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800925 assert(StackID < Timers->size());
926 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700927}
928
Jim Stichnothbbca7542015-02-11 16:08:31 -0800929// Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr
Jim Stichnoth8e928382015-02-02 17:03:08 -0800930// at the interface to take and transfer ownership, but they
931// internally store the raw Cfg pointer in the work queue. This
932// allows e.g. future queue optimizations such as the use of atomics
933// to modify queue elements.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800934void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) {
935 assert(Func);
936 OptQ.blockingPush(Func.release());
937 if (getFlags().isSequential())
938 translateFunctions();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800939}
940
Jim Stichnothbbca7542015-02-11 16:08:31 -0800941std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() {
942 return std::unique_ptr<Cfg>(OptQ.blockingPop());
943}
944
945void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) {
946 assert(Item);
947 EmitQ.blockingPush(Item);
948 if (getFlags().isSequential())
949 emitItems();
950}
951
952EmitterWorkItem *GlobalContext::emitQueueBlockingPop() {
953 return EmitQ.blockingPop();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800954}
955
Jim Stichnothff9c7062014-09-18 04:50:49 -0700956void GlobalContext::dumpStats(const IceString &Name, bool Final) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800957 if (!getFlags().getDumpStats())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800958 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800959 OstreamLocker OL(this);
960 if (Final) {
961 getStatsCumulative()->dump(Name, getStrDump());
962 } else {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800963 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump());
Jim Stichnoth18735602014-09-16 19:59:35 -0700964 }
965}
966
Jim Stichnoth8363a062014-10-07 10:02:38 -0700967void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700968 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800969 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800970 auto Timers = getTimers();
971 assert(Timers->size() > StackID);
972 OstreamLocker L(this);
973 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700974}
975
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800976void TimerMarker::push() {
977 switch (StackID) {
978 case GlobalContext::TSK_Default:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800979 Active = Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800980 break;
981 case GlobalContext::TSK_Funcs:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800982 Active = Ctx->getFlags().getTimeEachFunction();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800983 break;
984 default:
985 break;
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800986 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800987 if (Active)
988 Ctx->pushTimer(ID, StackID);
989}
990
991void TimerMarker::pushCfg(const Cfg *Func) {
992 Ctx = Func->getContext();
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800993 Active =
994 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800995 if (Active)
996 Ctx->pushTimer(ID, StackID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700997}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700998
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800999ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -08001000
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001001} // end of namespace Ice