blob: 4e8dc6b986354b75b4c2674b209d639afefb6e4a [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
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Defines aspects of the compilation that persist across multiple
Andrew Scull57e12682015-09-16 11:30:19 -070012/// functions.
Andrew Scull9612d322015-07-06 14:53:25 -070013///
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 Stichnoth98ba0062016-03-07 09:26:22 -080021#include "IceClFlagsExtra.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070022#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080023#include "IceELFObjectWriter.h"
Karl Schimpf9d98d792014-10-13 15:01:08 -070024#include "IceGlobalInits.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070025#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070026#include "IceTargetLowering.h"
Jim Stichnothc4554d72014-09-30 16:49:38 -070027#include "IceTimerTree.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070028#include "IceTypes.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070029
Jim Stichnothb0051df2016-01-13 11:39:15 -080030#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070031#pragma clang diagnostic push
32#pragma clang diagnostic ignored "-Wunused-parameter"
Jim Stichnothb0051df2016-01-13 11:39:15 -080033#endif // __clang__
34
John Porto67f8de92015-06-25 10:14:17 -070035#include "llvm/Support/Timer.h"
Jim Stichnothb0051df2016-01-13 11:39:15 -080036
37#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070038#pragma clang diagnostic pop
Jim Stichnothb0051df2016-01-13 11:39:15 -080039#endif // __clang__
John Porto67f8de92015-06-25 10:14:17 -070040
Qining Lu7cd53512015-06-26 09:36:00 -070041#include <algorithm> // max()
John Porto67f8de92015-06-25 10:14:17 -070042
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080043namespace std {
44template <> struct hash<Ice::RelocatableTuple> {
45 size_t operator()(const Ice::RelocatableTuple &Key) const {
John Porto27fddcc2016-02-02 15:06:09 -080046 if (!Key.EmitString.empty()) {
47 return hash<Ice::IceString>()(Key.EmitString);
48 }
49
John Portoe82b5602016-02-24 15:58:55 -080050 // If there's no emit string, then we use the relocatable's name, plus the
51 // hash of a combination of the number of OffsetExprs and the known, fixed
52 // offset for the reloc. We left shift the known relocatable by 5 trying to
53 // minimize the interaction between the bits in OffsetExpr.size() and
54 // Key.Offset.
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080055 return hash<Ice::IceString>()(Key.Name) +
John Portoe82b5602016-02-24 15:58:55 -080056 hash<std::size_t>()(Key.OffsetExpr.size() + (Key.Offset << 5));
Jim Stichnothd2cb4362014-11-20 11:24:42 -080057 }
58};
Jim Stichnothdddaf9c2014-12-04 14:09:21 -080059} // end of namespace std
Jim Stichnothd2cb4362014-11-20 11:24:42 -080060
Jim Stichnothf7c9a142014-04-29 10:52:43 -070061namespace Ice {
62
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070063namespace {
64
Andrew Scull57e12682015-09-16 11:30:19 -070065// Define the key comparison function for the constant pool's unordered_map,
66// but only for key types of interest: integer types, floating point types, and
67// the special RelocatableTuple.
Jim Stichnoth5bfe2152015-03-19 13:51:56 -070068template <typename KeyType, class Enable = void> struct KeyCompare {};
69
70template <typename KeyType>
71struct KeyCompare<KeyType,
72 typename std::enable_if<
73 std::is_integral<KeyType>::value ||
74 std::is_same<KeyType, RelocatableTuple>::value>::type> {
75 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
76 return Value1 == Value2;
77 }
78};
79template <typename KeyType>
80struct KeyCompare<KeyType, typename std::enable_if<
81 std::is_floating_point<KeyType>::value>::type> {
82 bool operator()(const KeyType &Value1, const KeyType &Value2) const {
83 return !memcmp(&Value1, &Value2, sizeof(KeyType));
84 }
85};
86
Andrew Scull57e12682015-09-16 11:30:19 -070087// Define a key comparison function for sorting the constant pool's values
88// after they are dumped to a vector. This covers integer types, floating point
89// types, and ConstantRelocatable values.
Jim Stichnoth6e293c82015-04-09 09:11:18 -070090template <typename ValueType, class Enable = void> struct KeyCompareLess {};
91
92template <typename ValueType>
93struct KeyCompareLess<ValueType,
94 typename std::enable_if<std::is_floating_point<
95 typename ValueType::PrimType>::value>::type> {
96 bool operator()(const Constant *Const1, const Constant *Const2) const {
Andrew Scull8072bae2015-09-14 16:01:26 -070097 using CompareType = uint64_t;
Jim Stichnoth6e293c82015-04-09 09:11:18 -070098 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType),
99 "Expected floating-point type of width 64-bit or less");
100 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
101 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
102 // We avoid "V1<V2" because of NaN.
103 // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the
104 // endian-ness of the host system running Subzero.
105 // Instead, compare the result of bit_cast to uint64_t.
106 uint64_t I1 = 0, I2 = 0;
107 memcpy(&I1, &V1, sizeof(V1));
108 memcpy(&I2, &V2, sizeof(V2));
109 return I1 < I2;
110 }
111};
112template <typename ValueType>
113struct KeyCompareLess<ValueType,
114 typename std::enable_if<std::is_integral<
115 typename ValueType::PrimType>::value>::type> {
116 bool operator()(const Constant *Const1, const Constant *Const2) const {
117 typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
118 typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
119 return V1 < V2;
120 }
121};
122template <typename ValueType>
123struct KeyCompareLess<
124 ValueType, typename std::enable_if<
125 std::is_same<ValueType, ConstantRelocatable>::value>::type> {
126 bool operator()(const Constant *Const1, const Constant *Const2) const {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700127 auto *V1 = llvm::cast<ValueType>(Const1);
128 auto *V2 = llvm::cast<ValueType>(Const2);
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700129 if (V1->getName() == V2->getName())
130 return V1->getOffset() < V2->getOffset();
131 return V1->getName() < V2->getName();
132 }
133};
134
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700135// TypePool maps constants of type KeyType (e.g. float) to pointers to
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800136// type ValueType (e.g. ConstantFloat).
137template <Type Ty, typename KeyType, typename ValueType> class TypePool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700138 TypePool(const TypePool &) = delete;
139 TypePool &operator=(const TypePool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700140
141public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700142 TypePool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800143 ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
144 auto Iter = Pool.find(Key);
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800145 if (Iter != Pool.end()) {
146 Iter->second->updateLookupCount();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700147 return Iter->second;
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800148 }
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800149 auto *Result = ValueType::create(Ctx, Ty, Key);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800150 Pool[Key] = Result;
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800151 Result->updateLookupCount();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700152 return Result;
153 }
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700154 ConstantList getConstantPool() const {
155 ConstantList Constants;
156 Constants.reserve(Pool.size());
Jim Stichnothf44f3712014-10-01 14:05:51 -0700157 for (auto &I : Pool)
158 Constants.push_back(I.second);
Andrew Scull8072bae2015-09-14 16:01:26 -0700159 // The sort (and its KeyCompareLess machinery) is not strictly necessary,
160 // but is desirable for producing output that is deterministic across
161 // unordered_map::iterator implementations.
Jim Stichnoth6e293c82015-04-09 09:11:18 -0700162 std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>());
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700163 return Constants;
164 }
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800165 size_t size() const { return Pool.size(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700166
167private:
Andrew Scull8072bae2015-09-14 16:01:26 -0700168 // Use the default hash function, and a custom key comparison function. The
169 // key comparison function for floating point variables can't use the default
170 // == based implementation because of special C++ semantics regarding +0.0,
171 // -0.0, and NaN comparison. However, it's OK to use the default hash for
172 // floating point values because KeyCompare is the final source of truth - in
173 // the worst case a "false" collision must be resolved.
174 using ContainerType =
175 std::unordered_map<KeyType, ValueType *, std::hash<KeyType>,
176 KeyCompare<KeyType>>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700177 ContainerType Pool;
178};
179
Matt Walad8f4a7d2014-06-18 09:55:03 -0700180// UndefPool maps ICE types to the corresponding ConstantUndef values.
181class UndefPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700182 UndefPool(const UndefPool &) = delete;
183 UndefPool &operator=(const UndefPool &) = delete;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700184
185public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700186 UndefPool() : Pool(IceType_NUM) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700187
188 ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
Jim Stichnothae953202014-12-20 06:17:49 -0800189 if (Pool[Ty] == nullptr)
Jim Stichnothb36757e2015-10-05 13:55:11 -0700190 Pool[Ty] = ConstantUndef::create(Ctx, Ty);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800191 return Pool[Ty];
Matt Walad8f4a7d2014-06-18 09:55:03 -0700192 }
193
194private:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800195 std::vector<ConstantUndef *> Pool;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700196};
197
Jim Stichnoth5bfe2152015-03-19 13:51:56 -0700198} // end of anonymous namespace
199
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700200// The global constant pool bundles individual pools of each type of
201// interest.
202class ConstantPool {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700203 ConstantPool(const ConstantPool &) = delete;
204 ConstantPool &operator=(const ConstantPool &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700205
206public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700207 ConstantPool() = default;
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800208 TypePool<IceType_f32, float, ConstantFloat> Floats;
209 TypePool<IceType_f64, double, ConstantDouble> Doubles;
210 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
211 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
212 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
213 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
214 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
215 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
Jan Voung261cae32015-02-01 10:31:03 -0800216 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable>
217 ExternRelocatables;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700218 UndefPool Undefs;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700219};
220
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800221void GlobalContext::CodeStats::dump(const IceString &Name, GlobalContext *Ctx) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700222 if (!BuildDefs::dump())
Jim Stichnoth639c9212014-12-11 10:04:32 -0800223 return;
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800224 OstreamLocker _(Ctx);
225 Ostream &Str = Ctx->getStrDump();
Jim Stichnotha1dd3cc2015-01-31 10:48:11 -0800226#define X(str, tag) \
227 Str << "|" << Name << "|" str "|" << Stats[CS_##tag] << "\n";
228 CODESTATS_TABLE
229#undef X
230 Str << "|" << Name << "|Spills+Fills|"
231 << Stats[CS_NumSpills] + Stats[CS_NumFills] << "\n";
Jim Stichnoth639c9212014-12-11 10:04:32 -0800232 Str << "|" << Name << "|Memory Usage|";
233 if (ssize_t MemUsed = llvm::TimeRecord::getCurrentTime(false).getMemUsed())
234 Str << MemUsed;
235 else
236 Str << "(requires '-track-memory')";
237 Str << "\n";
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800238 Str << "|" << Name << "|CPool Sizes ";
239 {
240 auto Pool = Ctx->getConstPool();
241 Str << "|f32=" << Pool->Floats.size();
242 Str << "|f64=" << Pool->Doubles.size();
243 Str << "|i1=" << Pool->Integers1.size();
244 Str << "|i8=" << Pool->Integers8.size();
245 Str << "|i16=" << Pool->Integers16.size();
246 Str << "|i32=" << Pool->Integers32.size();
247 Str << "|i64=" << Pool->Integers64.size();
248 Str << "|Rel=" << Pool->Relocatables.size();
249 Str << "|ExtRel=" << Pool->ExternRelocatables.size();
250 }
251 Str << "\n";
Jim Stichnoth639c9212014-12-11 10:04:32 -0800252}
253
Karl Schimpf2f67b922015-04-22 15:20:16 -0700254GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800255 ELFStreamer *ELFStr)
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800256 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800257 StrEmit(OsEmit), StrError(OsError), ObjectWriter(),
Jim Stichnothbbca7542015-02-11 16:08:31 -0800258 OptQ(/*Sequential=*/Flags.isSequential(),
259 /*MaxSize=*/Flags.getNumTranslationThreads()),
260 // EmitQ is allowed unlimited size.
John Porto8b1a7052015-06-17 13:20:08 -0700261 EmitQ(/*Sequential=*/Flags.isSequential()),
John Porto1bec8bc2015-06-22 10:51:13 -0700262 DataLowering(TargetDataLowering::createLowering(this)) {
Karl Schimpf2f67b922015-04-22 15:20:16 -0700263 assert(OsDump && "OsDump is not defined for GlobalContext");
264 assert(OsEmit && "OsEmit is not defined for GlobalContext");
265 assert(OsError && "OsError is not defined for GlobalContext");
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800266 // Make sure thread_local fields are properly initialized before any
267 // accesses are made. Do this here instead of at the start of
268 // main() so that all clients (e.g. unit tests) can benefit for
269 // free.
270 GlobalContext::TlsInit();
271 Cfg::TlsInit();
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800272 // Create a new ThreadContext for the current thread. No need to
273 // lock AllThreadContexts at this point since no other threads have
274 // access yet to this GlobalContext object.
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800275 ThreadContext *MyTLS = new ThreadContext();
276 AllThreadContexts.push_back(MyTLS);
277 ICE_TLS_SET_FIELD(TLS, MyTLS);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700278 // Pre-register built-in stack names.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700279 if (BuildDefs::dump()) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800280 // TODO(stichnot): There needs to be a strong relationship between
281 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800282 newTimerStackID("Total across all functions");
283 newTimerStackID("Per-function summary");
284 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800285 Timers.initInto(MyTLS->Timers);
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800286 switch (Flags.getOutFileType()) {
287 case FT_Elf:
Jan Voung08c3bcd2014-12-01 17:55:16 -0800288 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800289 break;
290 case FT_Asm:
291 case FT_Iasm:
292 break;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800293 }
John Porto1bec8bc2015-06-22 10:51:13 -0700294
295 // ProfileBlockInfoVarDecl is initialized here because it takes this as a
296 // parameter -- we want to
297 // ensure that at least this' member variables are initialized.
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800298 ProfileBlockInfoVarDecl = VariableDeclaration::createExternal(this);
John Porto8b1a7052015-06-17 13:20:08 -0700299 ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
300 ProfileBlockInfoVarDecl->setIsConstant(true);
301
302 // Note: if you change this symbol, make sure to update
303 // runtime/szrt_profiler.c as well.
304 ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info");
Jim Stichnoth94844f12015-11-04 16:06:16 -0800305
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800306 TargetLowering::staticInit(this);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700307}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700308
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800309void GlobalContext::translateFunctions() {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800310 while (std::unique_ptr<Cfg> Func = optQueueBlockingPop()) {
Jim Stichnoth8e928382015-02-02 17:03:08 -0800311 // Install Func in TLS for Cfg-specific container allocators.
John Portoe82b5602016-02-24 15:58:55 -0800312 CfgLocalAllocatorScope _(Func.get());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800313 // Reset per-function stats being accumulated in TLS.
314 resetStats();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800315 // Set verbose level to none if the current function does NOT
316 // match the -verbose-focus command-line option.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800317 if (!matchSymbolName(Func->getFunctionName(),
318 getFlags().getVerboseFocusOn()))
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800319 Func->setVerbose(IceV_None);
320 // Disable translation if -notranslate is specified, or if the
321 // current function matches the -translate-only option. If
322 // translation is disabled, just dump the high-level IR and
323 // continue.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800324 if (getFlags().getDisableTranslation() ||
325 !matchSymbolName(Func->getFunctionName(),
326 getFlags().getTranslateOnly())) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800327 Func->dump();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800328 continue; // Func goes out of scope and gets deleted
329 }
John Portof8b4cc82015-06-09 18:06:19 -0700330
Jim Stichnothbbca7542015-02-11 16:08:31 -0800331 Func->translate();
332 EmitterWorkItem *Item = nullptr;
333 if (Func->hasError()) {
334 getErrorStatus()->assign(EC_Translation);
335 OstreamLocker L(this);
Karl Schimpf2f67b922015-04-22 15:20:16 -0700336 getStrError() << "ICE translation error: " << Func->getFunctionName()
Jim Stichnothb40595a2016-01-29 06:14:31 -0800337 << ": " << Func->getError() << ": "
338 << Func->getFunctionNameAndSize() << "\n";
Jim Stichnothbbca7542015-02-11 16:08:31 -0800339 Item = new EmitterWorkItem(Func->getSequenceNumber());
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800340 } else {
Jim Stichnoth24824e72015-02-12 21:35:34 -0800341 Func->getAssembler<>()->setInternal(Func->getInternal());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800342 switch (getFlags().getOutFileType()) {
343 case FT_Elf:
344 case FT_Iasm: {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800345 Func->emitIAS();
346 // The Cfg has already emitted into the assembly buffer, so
347 // stats have been fully collected into this thread's TLS.
348 // Dump them before TLS is reset for the next Cfg.
Jim Stichnothb40595a2016-01-29 06:14:31 -0800349 dumpStats(Func->getFunctionNameAndSize());
Jim Stichnothbbca7542015-02-11 16:08:31 -0800350 Assembler *Asm = Func->releaseAssembler();
351 // Copy relevant fields into Asm before Func is deleted.
352 Asm->setFunctionName(Func->getFunctionName());
Jim Stichnothbbca7542015-02-11 16:08:31 -0800353 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm);
John Portof8b4cc82015-06-09 18:06:19 -0700354 Item->setGlobalInits(Func->getGlobalInits());
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800355 } break;
356 case FT_Asm:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800357 // The Cfg has not been emitted yet, so stats are not ready
358 // to be dumped.
John Portof8b4cc82015-06-09 18:06:19 -0700359 std::unique_ptr<VariableDeclarationList> GlobalInits =
360 Func->getGlobalInits();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800361 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release());
John Portof8b4cc82015-06-09 18:06:19 -0700362 Item->setGlobalInits(std::move(GlobalInits));
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800363 break;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800364 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800365 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800366 assert(Item);
367 emitQueueBlockingPush(Item);
Jim Stichnoth8e928382015-02-02 17:03:08 -0800368 // The Cfg now gets deleted as Func goes out of scope.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800369 }
370}
371
Jim Stichnothbbca7542015-02-11 16:08:31 -0800372namespace {
373
Jim Stichnothbbca7542015-02-11 16:08:31 -0800374// Ensure Pending is large enough that Pending[Index] is valid.
375void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) {
376 if (Index >= Pending.size())
377 Pending.resize(Index + 1);
378}
379
380} // end of anonymous namespace
381
Jan Voungfb792842015-06-11 15:27:50 -0700382void GlobalContext::emitFileHeader() {
383 TimerMarker T1(Ice::TimerStack::TT_emit, this);
384 if (getFlags().getOutFileType() == FT_Elf) {
385 getObjectWriter()->writeInitialELFHeader();
386 } else {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700387 if (!BuildDefs::dump()) {
Jim Stichnothc8799682015-06-22 13:04:10 -0700388 getStrError() << "emitFileHeader for non-ELF";
389 getErrorStatus()->assign(EC_Translation);
390 }
Jan Voungfb792842015-06-11 15:27:50 -0700391 TargetHeaderLowering::createLowering(this)->lower();
392 }
393}
394
Jim Stichnothcac003e2015-06-18 12:48:58 -0700395void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
John Porto8b1a7052015-06-17 13:20:08 -0700396
Andrew Scull86df4e92015-07-30 13:54:44 -0700397void GlobalContext::lowerJumpTables() { DataLowering->lowerJumpTables(); }
398
John Porto844211e2016-02-04 08:42:48 -0800399void GlobalContext::addBlockInfoPtrs(VariableDeclaration *ProfileBlockInfo) {
400 for (const VariableDeclaration *Global : Globals) {
401 if (Cfg::isProfileGlobal(*Global)) {
402 constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
403 ProfileBlockInfo->addInitializer(
404 VariableDeclaration::RelocInitializer::create(
405 Global,
406 {RelocOffset::create(this, BlockExecutionCounterOffset)}));
407 }
408 }
409}
410
John Porto8b1a7052015-06-17 13:20:08 -0700411void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
412 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800413 const bool DumpGlobalVariables = BuildDefs::dump() &&
414 (Flags.getVerbose() & IceV_GlobalInit) &&
415 Flags.getVerboseFocusOn().empty();
John Porto8b1a7052015-06-17 13:20:08 -0700416 if (DumpGlobalVariables) {
417 OstreamLocker L(this);
418 Ostream &Stream = getStrDump();
419 for (const Ice::VariableDeclaration *Global : Globals) {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800420 Global->dump(Stream);
John Porto8b1a7052015-06-17 13:20:08 -0700421 }
422 }
423 if (Flags.getDisableTranslation())
424 return;
425
John Porto844211e2016-02-04 08:42:48 -0800426 addBlockInfoPtrs(ProfileBlockInfoVarDecl);
Qining Lu7cd53512015-06-26 09:36:00 -0700427 // If we need to shuffle the layout of global variables, shuffle them now.
428 if (getFlags().shouldReorderGlobalVariables()) {
Qining Luaee5fa82015-08-20 14:59:03 -0700429 // Create a random number generator for global variable reordering.
430 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
431 RPE_GlobalVariableReordering);
Qining Lu7cd53512015-06-26 09:36:00 -0700432 RandomShuffle(Globals.begin(), Globals.end(),
Qining Luaee5fa82015-08-20 14:59:03 -0700433 [&RNG](int N) { return (uint32_t)RNG.next(N); });
Qining Lu7cd53512015-06-26 09:36:00 -0700434 }
John Porto8b1a7052015-06-17 13:20:08 -0700435 DataLowering->lowerGlobals(Globals, SectionSuffix);
John Porto1bec8bc2015-06-22 10:51:13 -0700436 for (VariableDeclaration *Var : Globals) {
437 Var->discardInitializers();
438 }
John Porto8b1a7052015-06-17 13:20:08 -0700439 Globals.clear();
440}
441
442void GlobalContext::lowerProfileData() {
John Porto1bec8bc2015-06-22 10:51:13 -0700443 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only
444 // ever be nullptr after this method completes. This assertion is a convoluted
445 // way of ensuring lowerProfileData is invoked a single time.
446 assert(ProfileBlockInfoVarDecl != nullptr);
John Porto8b1a7052015-06-17 13:20:08 -0700447 // This adds a 64-bit sentinel entry to the end of our array. For 32-bit
448 // architectures this will waste 4 bytes.
449 const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
450 ProfileBlockInfoVarDecl->addInitializer(
John Porto1bec8bc2015-06-22 10:51:13 -0700451 VariableDeclaration::ZeroInitializer::create(Sizeof64BitNullPtr));
452 Globals.push_back(ProfileBlockInfoVarDecl);
John Porto8b1a7052015-06-17 13:20:08 -0700453 constexpr char ProfileDataSection[] = "$sz_profiler$";
454 lowerGlobals(ProfileDataSection);
John Porto1bec8bc2015-06-22 10:51:13 -0700455 ProfileBlockInfoVarDecl = nullptr;
John Porto8b1a7052015-06-17 13:20:08 -0700456}
457
Jim Stichnothbbca7542015-02-11 16:08:31 -0800458void GlobalContext::emitItems() {
459 const bool Threaded = !getFlags().isSequential();
460 // Pending is a vector containing the reassembled, ordered list of
461 // work items. When we're ready for the next item, we first check
462 // whether it's in the Pending list. If not, we take an item from
463 // the work queue, and if it's not the item we're waiting for, we
464 // insert it into Pending and repeat. The work item is deleted
465 // after it is processed.
466 std::vector<EmitterWorkItem *> Pending;
467 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
Qining Lu7cd53512015-06-26 09:36:00 -0700468 uint32_t ShuffleStartIndex = DesiredSequenceNumber;
469 uint32_t ShuffleEndIndex = DesiredSequenceNumber;
470 bool EmitQueueEmpty = false;
471 const uint32_t ShuffleWindowSize =
472 std::max(1u, getFlags().getReorderFunctionsWindowSize());
473 bool Shuffle = Threaded && getFlags().shouldReorderFunctions();
Qining Luaee5fa82015-08-20 14:59:03 -0700474 // Create a random number generator for function reordering.
475 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering);
476
Qining Lu7cd53512015-06-26 09:36:00 -0700477 while (!EmitQueueEmpty) {
Jim Stichnothbbca7542015-02-11 16:08:31 -0800478 resizePending(Pending, DesiredSequenceNumber);
479 // See if Pending contains DesiredSequenceNumber.
480 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber];
Qining Lu7cd53512015-06-26 09:36:00 -0700481 if (RawItem == nullptr) {
482 // We need to fetch an EmitterWorkItem from the queue.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800483 RawItem = emitQueueBlockingPop();
Qining Lu7cd53512015-06-26 09:36:00 -0700484 if (RawItem == nullptr) {
485 // This is the notifier for an empty queue.
486 EmitQueueEmpty = true;
487 } else {
488 // We get an EmitterWorkItem, we need to add it to Pending.
489 uint32_t ItemSeq = RawItem->getSequenceNumber();
490 if (Threaded && ItemSeq != DesiredSequenceNumber) {
491 // Not the desired one, add it to Pending but do not increase
492 // DesiredSequenceNumber. Continue the loop, do not emit the item.
493 resizePending(Pending, ItemSeq);
494 Pending[ItemSeq] = RawItem;
495 continue;
496 }
497 // ItemSeq == DesiredSequenceNumber, we need to check if we should
498 // emit it or not. If !Threaded, we're OK with ItemSeq !=
499 // DesiredSequenceNumber.
500 Pending[DesiredSequenceNumber] = RawItem;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800501 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800502 }
Qining Lu7cd53512015-06-26 09:36:00 -0700503 // We have the desired EmitterWorkItem or nullptr as the end notifier.
504 // If the emitter queue is not empty, increase DesiredSequenceNumber and
505 // ShuffleEndIndex.
506 if (!EmitQueueEmpty) {
507 DesiredSequenceNumber++;
508 ShuffleEndIndex++;
509 }
510
511 if (Shuffle) {
512 // Continue fetching EmitterWorkItem if function reordering is turned on,
513 // and emit queue is not empty, and the number of consecutive pending
514 // items is smaller than the window size, and RawItem is not a
515 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid
516 // holding an arbitrarily large GlobalDeclarationList.
517 if (!EmitQueueEmpty &&
518 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize &&
519 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits)
520 continue;
521
522 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to
523 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the
524 // pending items from Pending[ShuffleStartIndex] to
525 // Pending[ShuffleEndIndex].
526 RandomShuffle(Pending.begin() + ShuffleStartIndex,
527 Pending.begin() + ShuffleEndIndex,
Qining Luaee5fa82015-08-20 14:59:03 -0700528 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
Qining Lu7cd53512015-06-26 09:36:00 -0700529 }
530
531 // Emit the item from ShuffleStartIndex to ShuffleEndIndex.
532 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
533 std::unique_ptr<EmitterWorkItem> Item(Pending[I]);
534
535 switch (Item->getKind()) {
536 case EmitterWorkItem::WI_Nop:
537 break;
538 case EmitterWorkItem::WI_GlobalInits: {
539 accumulateGlobals(Item->getGlobalInits());
540 } break;
541 case EmitterWorkItem::WI_Asm: {
542 lowerGlobalsIfNoCodeHasBeenSeen();
543 accumulateGlobals(Item->getGlobalInits());
544
545 std::unique_ptr<Assembler> Asm = Item->getAsm();
546 Asm->alignFunction();
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800547 const IceString &Name = Asm->getFunctionName();
Qining Lu7cd53512015-06-26 09:36:00 -0700548 switch (getFlags().getOutFileType()) {
549 case FT_Elf:
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800550 getObjectWriter()->writeFunctionCode(Name, Asm->getInternal(),
Qining Lu7cd53512015-06-26 09:36:00 -0700551 Asm.get());
552 break;
553 case FT_Iasm: {
554 OstreamLocker L(this);
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800555 Cfg::emitTextHeader(Name, this, Asm.get());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700556 Asm->emitIASBytes(this);
Qining Lu7cd53512015-06-26 09:36:00 -0700557 } break;
558 case FT_Asm:
559 llvm::report_fatal_error("Unexpected FT_Asm");
560 break;
561 }
562 } break;
563 case EmitterWorkItem::WI_Cfg: {
564 if (!BuildDefs::dump())
565 llvm::report_fatal_error("WI_Cfg work item created inappropriately");
566 lowerGlobalsIfNoCodeHasBeenSeen();
567 accumulateGlobals(Item->getGlobalInits());
568
569 assert(getFlags().getOutFileType() == FT_Asm);
570 std::unique_ptr<Cfg> Func = Item->getCfg();
571 // Unfortunately, we have to temporarily install the Cfg in TLS
572 // because Variable::asType() uses the allocator to create the
573 // differently-typed copy.
John Portoe82b5602016-02-24 15:58:55 -0800574 CfgLocalAllocatorScope _(Func.get());
Qining Lu7cd53512015-06-26 09:36:00 -0700575 Func->emit();
Jim Stichnothb40595a2016-01-29 06:14:31 -0800576 dumpStats(Func->getFunctionNameAndSize());
Qining Lu7cd53512015-06-26 09:36:00 -0700577 } break;
578 }
579 }
580 // Update the start index for next shuffling queue
581 ShuffleStartIndex = ShuffleEndIndex;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800582 }
John Portof8b4cc82015-06-09 18:06:19 -0700583
John Porto8b1a7052015-06-17 13:20:08 -0700584 // In case there are no code to be generated, we invoke the conditional
585 // lowerGlobals again -- this is a no-op if code has been emitted.
586 lowerGlobalsIfNoCodeHasBeenSeen();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800587}
588
Karl Schimpf9d98d792014-10-13 15:01:08 -0700589GlobalContext::~GlobalContext() {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800590 llvm::DeleteContainerPointers(AllThreadContexts);
John Porto1bec8bc2015-06-22 10:51:13 -0700591 LockedPtr<DestructorArray> Dtors = getDestructors();
592 // Destructors are invoked in the opposite object construction order.
Andrew Scull00741a02015-09-16 19:04:09 -0700593 for (const auto &Dtor : reverse_range(*Dtors))
594 Dtor();
Karl Schimpf9d98d792014-10-13 15:01:08 -0700595}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700596
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800597void GlobalContext::dumpConstantLookupCounts() {
598 if (!BuildDefs::dump())
599 return;
600 const bool DumpCounts = (Flags.getVerbose() & IceV_ConstPoolStats) &&
601 Flags.getVerboseFocusOn().empty();
602 if (!DumpCounts)
603 return;
604
605 OstreamLocker _(this);
606 Ostream &Str = getStrDump();
607 Str << "Constant pool use stats: count+value+type\n";
608#define X(WhichPool) \
609 for (auto *C : getConstPool()->WhichPool.getConstantPool()) { \
610 Str << C->getLookupCount() << " "; \
611 C->dump(Str); \
612 Str << " " << C->getType() << "\n"; \
613 }
614 X(Integers1);
615 X(Integers8);
616 X(Integers16);
617 X(Integers32);
618 X(Integers64);
619 X(Floats);
620 X(Doubles);
621 X(Relocatables);
622 X(ExternRelocatables);
623#undef X
624}
625
Andrew Scull57e12682015-09-16 11:30:19 -0700626// TODO(stichnot): Consider adding thread-local caches of constant pool entries
627// to reduce contention.
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800628
629// All locking is done by the getConstantInt[0-9]+() target function.
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800630Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
631 switch (Ty) {
632 case IceType_i1:
633 return getConstantInt1(Value);
634 case IceType_i8:
635 return getConstantInt8(Value);
636 case IceType_i16:
637 return getConstantInt16(Value);
638 case IceType_i32:
639 return getConstantInt32(Value);
640 case IceType_i64:
641 return getConstantInt64(Value);
642 default:
643 llvm_unreachable("Bad integer type for getConstant");
644 }
Jim Stichnothae953202014-12-20 06:17:49 -0800645 return nullptr;
Jan Voungbc004632014-09-16 15:09:10 -0700646}
647
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800648Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
649 ConstantInt1 &= INT8_C(1);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800650 return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800651}
652
653Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800654 return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800655}
656
657Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800658 return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800659}
660
661Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800662 return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800663}
664
665Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800666 return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700667}
668
669Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800670 return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700671}
672
673Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800674 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700675}
676
John Portoe82b5602016-02-24 15:58:55 -0800677Constant *GlobalContext::getConstantSym(const RelocOffsetT Offset,
678 const RelocOffsetArray &OffsetExpr,
John Porto27fddcc2016-02-02 15:06:09 -0800679 const IceString &Name,
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800680 const IceString &EmitString) {
John Porto27fddcc2016-02-02 15:06:09 -0800681 return getConstPool()->Relocatables.getOrAdd(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800682 this, RelocatableTuple(Offset, OffsetExpr, Name, EmitString));
John Porto27fddcc2016-02-02 15:06:09 -0800683}
684
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800685Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800686 const IceString &Name) {
John Porto27fddcc2016-02-02 15:06:09 -0800687 constexpr char EmptyEmitString[] = "";
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800688 return getConstantSym(Offset, {}, Name, EmptyEmitString);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700689}
690
Jan Voung261cae32015-02-01 10:31:03 -0800691Constant *GlobalContext::getConstantExternSym(const IceString &Name) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700692 constexpr RelocOffsetT Offset = 0;
Jan Voung261cae32015-02-01 10:31:03 -0800693 return getConstPool()->ExternRelocatables.getOrAdd(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800694 this, RelocatableTuple(Offset, {}, Name));
Jan Voung261cae32015-02-01 10:31:03 -0800695}
696
Matt Walad8f4a7d2014-06-18 09:55:03 -0700697Constant *GlobalContext::getConstantUndef(Type Ty) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800698 return getConstPool()->Undefs.getOrAdd(this, Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700699}
700
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800701// All locking is done by the getConstant*() target function.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700702Constant *GlobalContext::getConstantZero(Type Ty) {
703 switch (Ty) {
704 case IceType_i1:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800705 return getConstantInt1(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700706 case IceType_i8:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800707 return getConstantInt8(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700708 case IceType_i16:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800709 return getConstantInt16(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700710 case IceType_i32:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800711 return getConstantInt32(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700712 case IceType_i64:
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800713 return getConstantInt64(0);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700714 case IceType_f32:
715 return getConstantFloat(0);
716 case IceType_f64:
717 return getConstantDouble(0);
Matt Wala928f1292014-07-07 16:50:46 -0700718 case IceType_v4i1:
719 case IceType_v8i1:
720 case IceType_v16i1:
721 case IceType_v16i8:
722 case IceType_v8i16:
723 case IceType_v4i32:
724 case IceType_v4f32: {
725 IceString Str;
726 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700727 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700728 llvm_unreachable(BaseOS.str().c_str());
729 } break;
Matt Walad8f4a7d2014-06-18 09:55:03 -0700730 case IceType_void:
731 case IceType_NUM:
732 break;
733 }
734 llvm_unreachable("Unknown type");
735}
736
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800737ConstantList GlobalContext::getConstantPool(Type Ty) {
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700738 switch (Ty) {
739 case IceType_i1:
740 case IceType_i8:
Qining Lu253dc8a2015-06-22 10:10:23 -0700741 return getConstPool()->Integers8.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700742 case IceType_i16:
Qining Lu253dc8a2015-06-22 10:10:23 -0700743 return getConstPool()->Integers16.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700744 case IceType_i32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800745 return getConstPool()->Integers32.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700746 case IceType_i64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800747 return getConstPool()->Integers64.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700748 case IceType_f32:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800749 return getConstPool()->Floats.getConstantPool();
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700750 case IceType_f64:
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800751 return getConstPool()->Doubles.getConstantPool();
Matt Wala928f1292014-07-07 16:50:46 -0700752 case IceType_v4i1:
753 case IceType_v8i1:
754 case IceType_v16i1:
755 case IceType_v16i8:
756 case IceType_v8i16:
757 case IceType_v4i32:
758 case IceType_v4f32: {
759 IceString Str;
760 llvm::raw_string_ostream BaseOS(Str);
Jim Stichnoth78282f62014-07-27 23:14:00 -0700761 BaseOS << "Unsupported constant type: " << Ty;
Matt Wala928f1292014-07-07 16:50:46 -0700762 llvm_unreachable(BaseOS.str().c_str());
763 } break;
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700764 case IceType_void:
765 case IceType_NUM:
766 break;
767 }
768 llvm_unreachable("Unknown type");
769}
770
Jan Voung261cae32015-02-01 10:31:03 -0800771ConstantList GlobalContext::getConstantExternSyms() {
772 return getConstPool()->ExternRelocatables.getConstantPool();
773}
774
Andrew Scull1eda90a2015-08-04 17:03:19 -0700775JumpTableDataList GlobalContext::getJumpTables() {
776 JumpTableDataList JumpTables(*getJumpTableList());
Andrew Scull57e12682015-09-16 11:30:19 -0700777 // Make order deterministic by sorting into functions and then ID of the jump
778 // table within that function.
Qining Luaee5fa82015-08-20 14:59:03 -0700779 std::sort(JumpTables.begin(), JumpTables.end(),
780 [](const JumpTableData &A, const JumpTableData &B) {
781 if (A.getFunctionName() != B.getFunctionName())
782 return A.getFunctionName() < B.getFunctionName();
783 return A.getId() < B.getId();
784 });
785
Andrew Scull1eda90a2015-08-04 17:03:19 -0700786 if (getFlags().shouldReorderPooledConstants()) {
Qining Luaee5fa82015-08-20 14:59:03 -0700787 // If reorder-pooled-constants option is set to true, we also shuffle the
788 // jump tables before emitting them.
789
790 // Create a random number generator for jump tables reordering, considering
791 // jump tables as pooled constants.
792 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
793 RPE_PooledConstantReordering);
John Portoe0d9afa2015-08-05 10:13:44 -0700794 RandomShuffle(JumpTables.begin(), JumpTables.end(),
Qining Luaee5fa82015-08-20 14:59:03 -0700795 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
Andrew Scull1eda90a2015-08-04 17:03:19 -0700796 }
797 return JumpTables;
798}
799
David Sehr0fe6b542015-11-19 21:47:15 -0800800JumpTableData &
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800801GlobalContext::addJumpTable(const IceString &FuncName, SizeT Id,
David Sehr0fe6b542015-11-19 21:47:15 -0800802 const JumpTableData::TargetList &TargetList) {
Andrew Scull1eda90a2015-08-04 17:03:19 -0700803 auto JumpTableList = getJumpTableList();
David Sehr0fe6b542015-11-19 21:47:15 -0800804 JumpTableList->emplace_back(FuncName, Id, TargetList);
Andrew Scull1eda90a2015-08-04 17:03:19 -0700805 return JumpTableList->back();
Andrew Scull86df4e92015-07-30 13:54:44 -0700806}
807
Jim Stichnoth8363a062014-10-07 10:02:38 -0700808TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700809 if (!BuildDefs::dump())
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800810 return 0;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800811 auto Timers = getTimers();
812 TimerStackIdT NewID = Timers->size();
813 Timers->push_back(TimerStack(Name));
Jim Stichnoth8363a062014-10-07 10:02:38 -0700814 return NewID;
815}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700816
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800817TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
818 const IceString &Name) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800819 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800820 assert(StackID < Timers->size());
821 return Timers->at(StackID).getTimerID(Name);
822}
823
Jim Stichnoth8363a062014-10-07 10:02:38 -0700824void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800825 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800826 assert(StackID < Timers->size());
827 Timers->at(StackID).push(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700828}
829
830void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800831 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800832 assert(StackID < Timers->size());
833 Timers->at(StackID).pop(ID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700834}
Jim Stichnothc4554d72014-09-30 16:49:38 -0700835
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700836void GlobalContext::resetTimer(TimerStackIdT StackID) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800837 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800838 assert(StackID < Timers->size());
839 Timers->at(StackID).reset();
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700840}
841
842void GlobalContext::setTimerName(TimerStackIdT StackID,
843 const IceString &NewName) {
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800844 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800845 assert(StackID < Timers->size());
846 Timers->at(StackID).setName(NewName);
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700847}
848
Andrew Scull57e12682015-09-16 11:30:19 -0700849// Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the
850// interface to take and transfer ownership, but they internally store the raw
851// Cfg pointer in the work queue. This allows e.g. future queue optimizations
852// such as the use of atomics to modify queue elements.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800853void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) {
854 assert(Func);
855 OptQ.blockingPush(Func.release());
856 if (getFlags().isSequential())
857 translateFunctions();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800858}
859
Jim Stichnothbbca7542015-02-11 16:08:31 -0800860std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() {
861 return std::unique_ptr<Cfg>(OptQ.blockingPop());
862}
863
864void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) {
865 assert(Item);
866 EmitQ.blockingPush(Item);
867 if (getFlags().isSequential())
868 emitItems();
869}
870
871EmitterWorkItem *GlobalContext::emitQueueBlockingPop() {
872 return EmitQ.blockingPop();
Jim Stichnoth8e928382015-02-02 17:03:08 -0800873}
874
Jim Stichnothff9c7062014-09-18 04:50:49 -0700875void GlobalContext::dumpStats(const IceString &Name, bool Final) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800876 if (!getFlags().getDumpStats())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800877 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800878 if (Final) {
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800879 getStatsCumulative()->dump(Name, this);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800880 } else {
Jim Stichnoth3d5e08d2016-03-01 12:22:29 -0800881 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, this);
Jim Stichnoth18735602014-09-16 19:59:35 -0700882 }
883}
884
Jim Stichnoth8363a062014-10-07 10:02:38 -0700885void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700886 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800887 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800888 auto Timers = getTimers();
889 assert(Timers->size() > StackID);
890 OstreamLocker L(this);
891 Timers->at(StackID).dump(getStrDump(), DumpCumulative);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700892}
893
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800894ClFlags GlobalContext::Flags;
895ClFlagsExtra GlobalContext::ExtraFlags;
896
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800897void TimerMarker::push() {
898 switch (StackID) {
899 case GlobalContext::TSK_Default:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800900 Active = Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800901 break;
902 case GlobalContext::TSK_Funcs:
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800903 Active = Ctx->getFlags().getTimeEachFunction();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800904 break;
905 default:
906 break;
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800907 }
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800908 if (Active)
909 Ctx->pushTimer(ID, StackID);
910}
911
912void TimerMarker::pushCfg(const Cfg *Func) {
913 Ctx = Func->getContext();
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800914 Active =
915 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800916 if (Active)
917 Ctx->pushTimer(ID, StackID);
Jim Stichnoth8363a062014-10-07 10:02:38 -0700918}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700919
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800920ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800921
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700922} // end of namespace Ice