xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceGlobalContext.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Defines aspects of the compilation that persist across multiple
12*03ce13f7SAndroid Build Coastguard Worker /// functions.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker 
16*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalContext.h"
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceClFlags.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceELFObjectWriter.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalInits.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceLiveness.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "IceRevision.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "IceTimerTree.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.def"
30*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h"
31*03ce13f7SAndroid Build Coastguard Worker 
32*03ce13f7SAndroid Build Coastguard Worker #ifdef __clang__
33*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic push
34*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wunused-parameter"
35*03ce13f7SAndroid Build Coastguard Worker #endif // __clang__
36*03ce13f7SAndroid Build Coastguard Worker 
37*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Timer.h"
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker #ifdef __clang__
40*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic pop
41*03ce13f7SAndroid Build Coastguard Worker #endif // __clang__
42*03ce13f7SAndroid Build Coastguard Worker 
43*03ce13f7SAndroid Build Coastguard Worker #include <algorithm> // max()
44*03ce13f7SAndroid Build Coastguard Worker 
45*03ce13f7SAndroid Build Coastguard Worker namespace std {
46*03ce13f7SAndroid Build Coastguard Worker template <> struct hash<Ice::RelocatableTuple> {
operator ()std::hash47*03ce13f7SAndroid Build Coastguard Worker   size_t operator()(const Ice::RelocatableTuple &Key) const {
48*03ce13f7SAndroid Build Coastguard Worker     // Use the relocatable's name, plus the hash of a combination of the number
49*03ce13f7SAndroid Build Coastguard Worker     // of OffsetExprs and the known, fixed offset for the reloc. We left shift
50*03ce13f7SAndroid Build Coastguard Worker     // the known relocatable by 5 trying to minimize the interaction between the
51*03ce13f7SAndroid Build Coastguard Worker     // bits in OffsetExpr.size() and Key.Offset.
52*03ce13f7SAndroid Build Coastguard Worker     return hash<Ice::SizeT>()(Key.Name.getID()) +
53*03ce13f7SAndroid Build Coastguard Worker            hash<std::size_t>()(Key.OffsetExpr.size() + (Key.Offset << 5));
54*03ce13f7SAndroid Build Coastguard Worker   }
55*03ce13f7SAndroid Build Coastguard Worker };
56*03ce13f7SAndroid Build Coastguard Worker } // end of namespace std
57*03ce13f7SAndroid Build Coastguard Worker 
58*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
59*03ce13f7SAndroid Build Coastguard Worker 
60*03ce13f7SAndroid Build Coastguard Worker namespace {
61*03ce13f7SAndroid Build Coastguard Worker 
62*03ce13f7SAndroid Build Coastguard Worker // Define the key comparison function for the constant pool's unordered_map,
63*03ce13f7SAndroid Build Coastguard Worker // but only for key types of interest: integer types, floating point types, and
64*03ce13f7SAndroid Build Coastguard Worker // the special RelocatableTuple.
65*03ce13f7SAndroid Build Coastguard Worker template <typename KeyType, class Enable = void> struct KeyCompare {};
66*03ce13f7SAndroid Build Coastguard Worker 
67*03ce13f7SAndroid Build Coastguard Worker template <typename KeyType>
68*03ce13f7SAndroid Build Coastguard Worker struct KeyCompare<KeyType,
69*03ce13f7SAndroid Build Coastguard Worker                   typename std::enable_if<
70*03ce13f7SAndroid Build Coastguard Worker                       std::is_integral<KeyType>::value ||
71*03ce13f7SAndroid Build Coastguard Worker                       std::is_same<KeyType, RelocatableTuple>::value>::type> {
operator ()Ice::__anona455ce5b0111::KeyCompare72*03ce13f7SAndroid Build Coastguard Worker   bool operator()(const KeyType &Value1, const KeyType &Value2) const {
73*03ce13f7SAndroid Build Coastguard Worker     return Value1 == Value2;
74*03ce13f7SAndroid Build Coastguard Worker   }
75*03ce13f7SAndroid Build Coastguard Worker };
76*03ce13f7SAndroid Build Coastguard Worker template <typename KeyType>
77*03ce13f7SAndroid Build Coastguard Worker struct KeyCompare<KeyType, typename std::enable_if<
78*03ce13f7SAndroid Build Coastguard Worker                                std::is_floating_point<KeyType>::value>::type> {
operator ()Ice::__anona455ce5b0111::KeyCompare79*03ce13f7SAndroid Build Coastguard Worker   bool operator()(const KeyType &Value1, const KeyType &Value2) const {
80*03ce13f7SAndroid Build Coastguard Worker     return !memcmp(&Value1, &Value2, sizeof(KeyType));
81*03ce13f7SAndroid Build Coastguard Worker   }
82*03ce13f7SAndroid Build Coastguard Worker };
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker // Define a key comparison function for sorting the constant pool's values
85*03ce13f7SAndroid Build Coastguard Worker // after they are dumped to a vector. This covers integer types, floating point
86*03ce13f7SAndroid Build Coastguard Worker // types, and ConstantRelocatable values.
87*03ce13f7SAndroid Build Coastguard Worker template <typename ValueType, class Enable = void> struct KeyCompareLess {};
88*03ce13f7SAndroid Build Coastguard Worker 
89*03ce13f7SAndroid Build Coastguard Worker template <typename ValueType>
90*03ce13f7SAndroid Build Coastguard Worker struct KeyCompareLess<ValueType,
91*03ce13f7SAndroid Build Coastguard Worker                       typename std::enable_if<std::is_floating_point<
92*03ce13f7SAndroid Build Coastguard Worker                           typename ValueType::PrimType>::value>::type> {
operator ()Ice::__anona455ce5b0111::KeyCompareLess93*03ce13f7SAndroid Build Coastguard Worker   bool operator()(const Constant *Const1, const Constant *Const2) const {
94*03ce13f7SAndroid Build Coastguard Worker     using CompareType = uint64_t;
95*03ce13f7SAndroid Build Coastguard Worker     static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType),
96*03ce13f7SAndroid Build Coastguard Worker                   "Expected floating-point type of width 64-bit or less");
97*03ce13f7SAndroid Build Coastguard Worker     typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
98*03ce13f7SAndroid Build Coastguard Worker     typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
99*03ce13f7SAndroid Build Coastguard Worker     // We avoid "V1<V2" because of NaN.
100*03ce13f7SAndroid Build Coastguard Worker     // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the
101*03ce13f7SAndroid Build Coastguard Worker     // endian-ness of the host system running Subzero.
102*03ce13f7SAndroid Build Coastguard Worker     // Instead, compare the result of bit_cast to uint64_t.
103*03ce13f7SAndroid Build Coastguard Worker     uint64_t I1 = 0, I2 = 0;
104*03ce13f7SAndroid Build Coastguard Worker     memcpy(&I1, &V1, sizeof(V1));
105*03ce13f7SAndroid Build Coastguard Worker     memcpy(&I2, &V2, sizeof(V2));
106*03ce13f7SAndroid Build Coastguard Worker     return I1 < I2;
107*03ce13f7SAndroid Build Coastguard Worker   }
108*03ce13f7SAndroid Build Coastguard Worker };
109*03ce13f7SAndroid Build Coastguard Worker template <typename ValueType>
110*03ce13f7SAndroid Build Coastguard Worker struct KeyCompareLess<ValueType,
111*03ce13f7SAndroid Build Coastguard Worker                       typename std::enable_if<std::is_integral<
112*03ce13f7SAndroid Build Coastguard Worker                           typename ValueType::PrimType>::value>::type> {
operator ()Ice::__anona455ce5b0111::KeyCompareLess113*03ce13f7SAndroid Build Coastguard Worker   bool operator()(const Constant *Const1, const Constant *Const2) const {
114*03ce13f7SAndroid Build Coastguard Worker     typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
115*03ce13f7SAndroid Build Coastguard Worker     typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
116*03ce13f7SAndroid Build Coastguard Worker     return V1 < V2;
117*03ce13f7SAndroid Build Coastguard Worker   }
118*03ce13f7SAndroid Build Coastguard Worker };
119*03ce13f7SAndroid Build Coastguard Worker template <typename ValueType>
120*03ce13f7SAndroid Build Coastguard Worker struct KeyCompareLess<
121*03ce13f7SAndroid Build Coastguard Worker     ValueType, typename std::enable_if<
122*03ce13f7SAndroid Build Coastguard Worker                    std::is_same<ValueType, ConstantRelocatable>::value>::type> {
operator ()Ice::__anona455ce5b0111::KeyCompareLess123*03ce13f7SAndroid Build Coastguard Worker   bool operator()(const Constant *Const1, const Constant *Const2) const {
124*03ce13f7SAndroid Build Coastguard Worker     auto *V1 = llvm::cast<ValueType>(Const1);
125*03ce13f7SAndroid Build Coastguard Worker     auto *V2 = llvm::cast<ValueType>(Const2);
126*03ce13f7SAndroid Build Coastguard Worker     if (V1->getName() == V2->getName())
127*03ce13f7SAndroid Build Coastguard Worker       return V1->getOffset() < V2->getOffset();
128*03ce13f7SAndroid Build Coastguard Worker     return V1->getName() < V2->getName();
129*03ce13f7SAndroid Build Coastguard Worker   }
130*03ce13f7SAndroid Build Coastguard Worker };
131*03ce13f7SAndroid Build Coastguard Worker 
132*03ce13f7SAndroid Build Coastguard Worker // TypePool maps constants of type KeyType (e.g. float) to pointers to
133*03ce13f7SAndroid Build Coastguard Worker // type ValueType (e.g. ConstantFloat).
134*03ce13f7SAndroid Build Coastguard Worker template <Type Ty, typename KeyType, typename ValueType> class TypePool {
135*03ce13f7SAndroid Build Coastguard Worker   TypePool(const TypePool &) = delete;
136*03ce13f7SAndroid Build Coastguard Worker   TypePool &operator=(const TypePool &) = delete;
137*03ce13f7SAndroid Build Coastguard Worker 
138*03ce13f7SAndroid Build Coastguard Worker public:
139*03ce13f7SAndroid Build Coastguard Worker   TypePool() = default;
getOrAdd(GlobalContext * Ctx,KeyType Key)140*03ce13f7SAndroid Build Coastguard Worker   ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
141*03ce13f7SAndroid Build Coastguard Worker     auto Iter = Pool.find(Key);
142*03ce13f7SAndroid Build Coastguard Worker     if (Iter != Pool.end()) {
143*03ce13f7SAndroid Build Coastguard Worker       Iter->second->updateLookupCount();
144*03ce13f7SAndroid Build Coastguard Worker       return Iter->second;
145*03ce13f7SAndroid Build Coastguard Worker     }
146*03ce13f7SAndroid Build Coastguard Worker     auto *Result = ValueType::create(Ctx, Ty, Key);
147*03ce13f7SAndroid Build Coastguard Worker     Pool[Key] = Result;
148*03ce13f7SAndroid Build Coastguard Worker     Result->updateLookupCount();
149*03ce13f7SAndroid Build Coastguard Worker     return Result;
150*03ce13f7SAndroid Build Coastguard Worker   }
getConstantPool() const151*03ce13f7SAndroid Build Coastguard Worker   ConstantList getConstantPool() const {
152*03ce13f7SAndroid Build Coastguard Worker     ConstantList Constants;
153*03ce13f7SAndroid Build Coastguard Worker     Constants.reserve(Pool.size());
154*03ce13f7SAndroid Build Coastguard Worker     for (auto &I : Pool)
155*03ce13f7SAndroid Build Coastguard Worker       Constants.push_back(I.second);
156*03ce13f7SAndroid Build Coastguard Worker     // The sort (and its KeyCompareLess machinery) is not strictly necessary,
157*03ce13f7SAndroid Build Coastguard Worker     // but is desirable for producing output that is deterministic across
158*03ce13f7SAndroid Build Coastguard Worker     // unordered_map::iterator implementations.
159*03ce13f7SAndroid Build Coastguard Worker     std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>());
160*03ce13f7SAndroid Build Coastguard Worker     return Constants;
161*03ce13f7SAndroid Build Coastguard Worker   }
size() const162*03ce13f7SAndroid Build Coastguard Worker   size_t size() const { return Pool.size(); }
163*03ce13f7SAndroid Build Coastguard Worker 
164*03ce13f7SAndroid Build Coastguard Worker private:
165*03ce13f7SAndroid Build Coastguard Worker   // Use the default hash function, and a custom key comparison function. The
166*03ce13f7SAndroid Build Coastguard Worker   // key comparison function for floating point variables can't use the default
167*03ce13f7SAndroid Build Coastguard Worker   // == based implementation because of special C++ semantics regarding +0.0,
168*03ce13f7SAndroid Build Coastguard Worker   // -0.0, and NaN comparison. However, it's OK to use the default hash for
169*03ce13f7SAndroid Build Coastguard Worker   // floating point values because KeyCompare is the final source of truth - in
170*03ce13f7SAndroid Build Coastguard Worker   // the worst case a "false" collision must be resolved.
171*03ce13f7SAndroid Build Coastguard Worker   using ContainerType =
172*03ce13f7SAndroid Build Coastguard Worker       std::unordered_map<KeyType, ValueType *, std::hash<KeyType>,
173*03ce13f7SAndroid Build Coastguard Worker                          KeyCompare<KeyType>>;
174*03ce13f7SAndroid Build Coastguard Worker   ContainerType Pool;
175*03ce13f7SAndroid Build Coastguard Worker };
176*03ce13f7SAndroid Build Coastguard Worker 
177*03ce13f7SAndroid Build Coastguard Worker // UndefPool maps ICE types to the corresponding ConstantUndef values.
178*03ce13f7SAndroid Build Coastguard Worker class UndefPool {
179*03ce13f7SAndroid Build Coastguard Worker   UndefPool(const UndefPool &) = delete;
180*03ce13f7SAndroid Build Coastguard Worker   UndefPool &operator=(const UndefPool &) = delete;
181*03ce13f7SAndroid Build Coastguard Worker 
182*03ce13f7SAndroid Build Coastguard Worker public:
UndefPool()183*03ce13f7SAndroid Build Coastguard Worker   UndefPool() : Pool(IceType_NUM) {}
184*03ce13f7SAndroid Build Coastguard Worker 
getOrAdd(GlobalContext * Ctx,Type Ty)185*03ce13f7SAndroid Build Coastguard Worker   ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
186*03ce13f7SAndroid Build Coastguard Worker     if (Pool[Ty] == nullptr)
187*03ce13f7SAndroid Build Coastguard Worker       Pool[Ty] = ConstantUndef::create(Ctx, Ty);
188*03ce13f7SAndroid Build Coastguard Worker     return Pool[Ty];
189*03ce13f7SAndroid Build Coastguard Worker   }
190*03ce13f7SAndroid Build Coastguard Worker 
191*03ce13f7SAndroid Build Coastguard Worker private:
192*03ce13f7SAndroid Build Coastguard Worker   std::vector<ConstantUndef *> Pool;
193*03ce13f7SAndroid Build Coastguard Worker };
194*03ce13f7SAndroid Build Coastguard Worker 
195*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
196*03ce13f7SAndroid Build Coastguard Worker 
197*03ce13f7SAndroid Build Coastguard Worker // The global constant pool bundles individual pools of each type of
198*03ce13f7SAndroid Build Coastguard Worker // interest.
199*03ce13f7SAndroid Build Coastguard Worker class ConstantPool {
200*03ce13f7SAndroid Build Coastguard Worker   ConstantPool(const ConstantPool &) = delete;
201*03ce13f7SAndroid Build Coastguard Worker   ConstantPool &operator=(const ConstantPool &) = delete;
202*03ce13f7SAndroid Build Coastguard Worker 
203*03ce13f7SAndroid Build Coastguard Worker public:
204*03ce13f7SAndroid Build Coastguard Worker   ConstantPool() = default;
205*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_f32, float, ConstantFloat> Floats;
206*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_f64, double, ConstantDouble> Doubles;
207*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
208*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
209*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
210*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
211*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
212*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
213*03ce13f7SAndroid Build Coastguard Worker   TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable>
214*03ce13f7SAndroid Build Coastguard Worker       ExternRelocatables;
215*03ce13f7SAndroid Build Coastguard Worker   UndefPool Undefs;
216*03ce13f7SAndroid Build Coastguard Worker };
217*03ce13f7SAndroid Build Coastguard Worker 
waitForWorkerThreads()218*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::waitForWorkerThreads() {
219*03ce13f7SAndroid Build Coastguard Worker   if (WaitForWorkerThreadsCalled.exchange(true))
220*03ce13f7SAndroid Build Coastguard Worker     return;
221*03ce13f7SAndroid Build Coastguard Worker   optQueueNotifyEnd();
222*03ce13f7SAndroid Build Coastguard Worker   for (std::thread &Worker : TranslationThreads) {
223*03ce13f7SAndroid Build Coastguard Worker     Worker.join();
224*03ce13f7SAndroid Build Coastguard Worker   }
225*03ce13f7SAndroid Build Coastguard Worker   TranslationThreads.clear();
226*03ce13f7SAndroid Build Coastguard Worker 
227*03ce13f7SAndroid Build Coastguard Worker   // Only notify the emit queue to end after all the translation threads have
228*03ce13f7SAndroid Build Coastguard Worker   // ended.
229*03ce13f7SAndroid Build Coastguard Worker   emitQueueNotifyEnd();
230*03ce13f7SAndroid Build Coastguard Worker   for (std::thread &Worker : EmitterThreads) {
231*03ce13f7SAndroid Build Coastguard Worker     Worker.join();
232*03ce13f7SAndroid Build Coastguard Worker   }
233*03ce13f7SAndroid Build Coastguard Worker   EmitterThreads.clear();
234*03ce13f7SAndroid Build Coastguard Worker 
235*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::timers()) {
236*03ce13f7SAndroid Build Coastguard Worker     auto Timers = getTimers();
237*03ce13f7SAndroid Build Coastguard Worker     for (ThreadContext *TLS : AllThreadContexts)
238*03ce13f7SAndroid Build Coastguard Worker       Timers->mergeFrom(TLS->Timers);
239*03ce13f7SAndroid Build Coastguard Worker   }
240*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::dump()) {
241*03ce13f7SAndroid Build Coastguard Worker     // Do a separate loop over AllThreadContexts to avoid holding two locks at
242*03ce13f7SAndroid Build Coastguard Worker     // once.
243*03ce13f7SAndroid Build Coastguard Worker     auto Stats = getStatsCumulative();
244*03ce13f7SAndroid Build Coastguard Worker     for (ThreadContext *TLS : AllThreadContexts)
245*03ce13f7SAndroid Build Coastguard Worker       Stats->add(TLS->StatsCumulative);
246*03ce13f7SAndroid Build Coastguard Worker   }
247*03ce13f7SAndroid Build Coastguard Worker }
248*03ce13f7SAndroid Build Coastguard Worker 
dump(const Cfg * Func,GlobalContext * Ctx)249*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::CodeStats::dump(const Cfg *Func, GlobalContext *Ctx) {
250*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
251*03ce13f7SAndroid Build Coastguard Worker     return;
252*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker _(Ctx);
253*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = Ctx->getStrDump();
254*03ce13f7SAndroid Build Coastguard Worker   const std::string Name =
255*03ce13f7SAndroid Build Coastguard Worker       (Func == nullptr ? "_FINAL_" : Func->getFunctionNameAndSize());
256*03ce13f7SAndroid Build Coastguard Worker #define X(str, tag)                                                            \
257*03ce13f7SAndroid Build Coastguard Worker   Str << "|" << Name << "|" str "|" << Stats[CS_##tag] << "\n";
258*03ce13f7SAndroid Build Coastguard Worker   CODESTATS_TABLE
259*03ce13f7SAndroid Build Coastguard Worker #undef X
260*03ce13f7SAndroid Build Coastguard Worker   Str << "|" << Name << "|Spills+Fills|"
261*03ce13f7SAndroid Build Coastguard Worker       << Stats[CS_NumSpills] + Stats[CS_NumFills] << "\n";
262*03ce13f7SAndroid Build Coastguard Worker   Str << "|" << Name << "|Memory Usage     |";
263*03ce13f7SAndroid Build Coastguard Worker   if (const auto MemUsed = static_cast<size_t>(
264*03ce13f7SAndroid Build Coastguard Worker           llvm::TimeRecord::getCurrentTime(false).getMemUsed())) {
265*03ce13f7SAndroid Build Coastguard Worker     static constexpr size_t _1MB = 1024 * 1024;
266*03ce13f7SAndroid Build Coastguard Worker     Str << (MemUsed / _1MB) << " MB";
267*03ce13f7SAndroid Build Coastguard Worker   } else {
268*03ce13f7SAndroid Build Coastguard Worker     Str << "(requires '-track-memory')";
269*03ce13f7SAndroid Build Coastguard Worker   }
270*03ce13f7SAndroid Build Coastguard Worker   Str << "\n";
271*03ce13f7SAndroid Build Coastguard Worker   Str << "|" << Name << "|CPool Sizes ";
272*03ce13f7SAndroid Build Coastguard Worker   {
273*03ce13f7SAndroid Build Coastguard Worker     auto Pool = Ctx->getConstPool();
274*03ce13f7SAndroid Build Coastguard Worker     Str << "|f32=" << Pool->Floats.size();
275*03ce13f7SAndroid Build Coastguard Worker     Str << "|f64=" << Pool->Doubles.size();
276*03ce13f7SAndroid Build Coastguard Worker     Str << "|i1=" << Pool->Integers1.size();
277*03ce13f7SAndroid Build Coastguard Worker     Str << "|i8=" << Pool->Integers8.size();
278*03ce13f7SAndroid Build Coastguard Worker     Str << "|i16=" << Pool->Integers16.size();
279*03ce13f7SAndroid Build Coastguard Worker     Str << "|i32=" << Pool->Integers32.size();
280*03ce13f7SAndroid Build Coastguard Worker     Str << "|i64=" << Pool->Integers64.size();
281*03ce13f7SAndroid Build Coastguard Worker     Str << "|Rel=" << Pool->Relocatables.size();
282*03ce13f7SAndroid Build Coastguard Worker     Str << "|ExtRel=" << Pool->ExternRelocatables.size();
283*03ce13f7SAndroid Build Coastguard Worker   }
284*03ce13f7SAndroid Build Coastguard Worker   Str << "\n";
285*03ce13f7SAndroid Build Coastguard Worker   if (Func != nullptr) {
286*03ce13f7SAndroid Build Coastguard Worker     Str << "|" << Name << "|Cfg Memory       |" << Func->getTotalMemoryMB()
287*03ce13f7SAndroid Build Coastguard Worker         << " MB\n";
288*03ce13f7SAndroid Build Coastguard Worker     Str << "|" << Name << "|Liveness Memory  |" << Func->getLivenessMemoryMB()
289*03ce13f7SAndroid Build Coastguard Worker         << " MB\n";
290*03ce13f7SAndroid Build Coastguard Worker   }
291*03ce13f7SAndroid Build Coastguard Worker }
292*03ce13f7SAndroid Build Coastguard Worker 
293*03ce13f7SAndroid Build Coastguard Worker namespace {
294*03ce13f7SAndroid Build Coastguard Worker 
295*03ce13f7SAndroid Build Coastguard Worker // By default, wake up the main parser thread when the OptQ gets half empty.
296*03ce13f7SAndroid Build Coastguard Worker static constexpr size_t DefaultOptQWakeupSize = GlobalContext::MaxOptQSize >> 1;
297*03ce13f7SAndroid Build Coastguard Worker 
298*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
299*03ce13f7SAndroid Build Coastguard Worker 
GlobalContext(Ostream * OsDump,Ostream * OsEmit,Ostream * OsError,ELFStreamer * ELFStr)300*03ce13f7SAndroid Build Coastguard Worker GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
301*03ce13f7SAndroid Build Coastguard Worker                              ELFStreamer *ELFStr)
302*03ce13f7SAndroid Build Coastguard Worker     : Strings(new StringPool()), ConstPool(new ConstantPool()), ErrorStatus(),
303*03ce13f7SAndroid Build Coastguard Worker       StrDump(OsDump), StrEmit(OsEmit), StrError(OsError), ObjectWriter(),
304*03ce13f7SAndroid Build Coastguard Worker       OptQWakeupSize(std::max(DefaultOptQWakeupSize,
305*03ce13f7SAndroid Build Coastguard Worker                               size_t(getFlags().getNumTranslationThreads()))),
306*03ce13f7SAndroid Build Coastguard Worker       OptQ(/*Sequential=*/getFlags().isSequential(),
307*03ce13f7SAndroid Build Coastguard Worker            /*MaxSize=*/
308*03ce13f7SAndroid Build Coastguard Worker            getFlags().isParseParallel()
309*03ce13f7SAndroid Build Coastguard Worker                ? MaxOptQSize
310*03ce13f7SAndroid Build Coastguard Worker                : getFlags().getNumTranslationThreads()),
311*03ce13f7SAndroid Build Coastguard Worker       // EmitQ is allowed unlimited size.
312*03ce13f7SAndroid Build Coastguard Worker       EmitQ(/*Sequential=*/getFlags().isSequential()),
313*03ce13f7SAndroid Build Coastguard Worker       DataLowering(TargetDataLowering::createLowering(this)) {
314*03ce13f7SAndroid Build Coastguard Worker   assert(OsDump && "OsDump is not defined for GlobalContext");
315*03ce13f7SAndroid Build Coastguard Worker   assert(OsEmit && "OsEmit is not defined for GlobalContext");
316*03ce13f7SAndroid Build Coastguard Worker   assert(OsError && "OsError is not defined for GlobalContext");
317*03ce13f7SAndroid Build Coastguard Worker   // Make sure thread_local fields are properly initialized before any
318*03ce13f7SAndroid Build Coastguard Worker   // accesses are made.  Do this here instead of at the start of
319*03ce13f7SAndroid Build Coastguard Worker   // main() so that all clients (e.g. unit tests) can benefit for
320*03ce13f7SAndroid Build Coastguard Worker   // free.
321*03ce13f7SAndroid Build Coastguard Worker   GlobalContext::TlsInit();
322*03ce13f7SAndroid Build Coastguard Worker   Cfg::TlsInit();
323*03ce13f7SAndroid Build Coastguard Worker   Liveness::TlsInit();
324*03ce13f7SAndroid Build Coastguard Worker   // Create a new ThreadContext for the current thread.  No need to
325*03ce13f7SAndroid Build Coastguard Worker   // lock AllThreadContexts at this point since no other threads have
326*03ce13f7SAndroid Build Coastguard Worker   // access yet to this GlobalContext object.
327*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *MyTLS = new ThreadContext();
328*03ce13f7SAndroid Build Coastguard Worker   AllThreadContexts.push_back(MyTLS);
329*03ce13f7SAndroid Build Coastguard Worker   ICE_TLS_SET_FIELD(TLS, MyTLS);
330*03ce13f7SAndroid Build Coastguard Worker   // Pre-register built-in stack names.
331*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::timers()) {
332*03ce13f7SAndroid Build Coastguard Worker     // TODO(stichnot): There needs to be a strong relationship between
333*03ce13f7SAndroid Build Coastguard Worker     // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
334*03ce13f7SAndroid Build Coastguard Worker     newTimerStackID("Total across all functions");
335*03ce13f7SAndroid Build Coastguard Worker     newTimerStackID("Per-function summary");
336*03ce13f7SAndroid Build Coastguard Worker   }
337*03ce13f7SAndroid Build Coastguard Worker   Timers.initInto(MyTLS->Timers);
338*03ce13f7SAndroid Build Coastguard Worker   switch (getFlags().getOutFileType()) {
339*03ce13f7SAndroid Build Coastguard Worker   case FT_Elf:
340*03ce13f7SAndroid Build Coastguard Worker     ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
341*03ce13f7SAndroid Build Coastguard Worker     break;
342*03ce13f7SAndroid Build Coastguard Worker   case FT_Asm:
343*03ce13f7SAndroid Build Coastguard Worker   case FT_Iasm:
344*03ce13f7SAndroid Build Coastguard Worker     break;
345*03ce13f7SAndroid Build Coastguard Worker   }
346*03ce13f7SAndroid Build Coastguard Worker // Cache up front common constants.
347*03ce13f7SAndroid Build Coastguard Worker #define X(tag, sizeLog2, align, elts, elty, str, rcstr)                        \
348*03ce13f7SAndroid Build Coastguard Worker   ConstZeroForType[IceType_##tag] = getConstantZeroInternal(IceType_##tag);
349*03ce13f7SAndroid Build Coastguard Worker   ICETYPE_TABLE;
350*03ce13f7SAndroid Build Coastguard Worker #undef X
351*03ce13f7SAndroid Build Coastguard Worker   ConstantTrue = getConstantInt1Internal(1);
352*03ce13f7SAndroid Build Coastguard Worker // Define runtime helper functions.
353*03ce13f7SAndroid Build Coastguard Worker #define X(Tag, Name)                                                           \
354*03ce13f7SAndroid Build Coastguard Worker   RuntimeHelperFunc[static_cast<size_t>(RuntimeHelper::H_##Tag)] =             \
355*03ce13f7SAndroid Build Coastguard Worker       getConstantExternSym(getGlobalString(Name));
356*03ce13f7SAndroid Build Coastguard Worker   RUNTIME_HELPER_FUNCTIONS_TABLE
357*03ce13f7SAndroid Build Coastguard Worker #undef X
358*03ce13f7SAndroid Build Coastguard Worker 
359*03ce13f7SAndroid Build Coastguard Worker   TargetLowering::staticInit(this);
360*03ce13f7SAndroid Build Coastguard Worker 
361*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().getEmitRevision()) {
362*03ce13f7SAndroid Build Coastguard Worker     // Embed the Subzero revision into the compiled binary by creating a special
363*03ce13f7SAndroid Build Coastguard Worker     // global variable initialized with the revision string.
364*03ce13f7SAndroid Build Coastguard Worker     auto *Revision = VariableDeclaration::create(&Globals, true);
365*03ce13f7SAndroid Build Coastguard Worker     Revision->setName(this, "__Sz_revision");
366*03ce13f7SAndroid Build Coastguard Worker     Revision->setIsConstant(true);
367*03ce13f7SAndroid Build Coastguard Worker     const char *RevisionString = getSubzeroRevision();
368*03ce13f7SAndroid Build Coastguard Worker     Revision->addInitializer(VariableDeclaration::DataInitializer::create(
369*03ce13f7SAndroid Build Coastguard Worker         &Globals, RevisionString, 1 + strlen(RevisionString)));
370*03ce13f7SAndroid Build Coastguard Worker     Globals.push_back(Revision);
371*03ce13f7SAndroid Build Coastguard Worker   }
372*03ce13f7SAndroid Build Coastguard Worker }
373*03ce13f7SAndroid Build Coastguard Worker 
translateFunctionsWrapper(ThreadContext * MyTLS)374*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::translateFunctionsWrapper(ThreadContext *MyTLS) {
375*03ce13f7SAndroid Build Coastguard Worker   ICE_TLS_SET_FIELD(TLS, MyTLS);
376*03ce13f7SAndroid Build Coastguard Worker   translateFunctions();
377*03ce13f7SAndroid Build Coastguard Worker }
378*03ce13f7SAndroid Build Coastguard Worker 
translateFunctions()379*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::translateFunctions() {
380*03ce13f7SAndroid Build Coastguard Worker   TimerMarker Timer(TimerStack::TT_translateFunctions, this);
381*03ce13f7SAndroid Build Coastguard Worker   while (std::unique_ptr<OptWorkItem> OptItem = optQueueBlockingPop()) {
382*03ce13f7SAndroid Build Coastguard Worker     std::unique_ptr<EmitterWorkItem> Item;
383*03ce13f7SAndroid Build Coastguard Worker     auto Func = OptItem->getParsedCfg();
384*03ce13f7SAndroid Build Coastguard Worker     // Install Func in TLS for Cfg-specific container allocators.
385*03ce13f7SAndroid Build Coastguard Worker     CfgLocalAllocatorScope _(Func.get());
386*03ce13f7SAndroid Build Coastguard Worker     // Reset per-function stats being accumulated in TLS.
387*03ce13f7SAndroid Build Coastguard Worker     resetStats();
388*03ce13f7SAndroid Build Coastguard Worker     // Set verbose level to none if the current function does NOT match the
389*03ce13f7SAndroid Build Coastguard Worker     // -verbose-focus command-line option.
390*03ce13f7SAndroid Build Coastguard Worker     if (!getFlags().matchVerboseFocusOn(Func->getFunctionName(),
391*03ce13f7SAndroid Build Coastguard Worker                                         Func->getSequenceNumber()))
392*03ce13f7SAndroid Build Coastguard Worker       Func->setVerbose(IceV_None);
393*03ce13f7SAndroid Build Coastguard Worker     // Disable translation if -notranslate is specified, or if the current
394*03ce13f7SAndroid Build Coastguard Worker     // function matches the -translate-only option.  If translation is disabled,
395*03ce13f7SAndroid Build Coastguard Worker     // just dump the high-level IR and continue.
396*03ce13f7SAndroid Build Coastguard Worker     if (getFlags().getDisableTranslation() ||
397*03ce13f7SAndroid Build Coastguard Worker         !getFlags().matchTranslateOnly(Func->getFunctionName(),
398*03ce13f7SAndroid Build Coastguard Worker                                        Func->getSequenceNumber())) {
399*03ce13f7SAndroid Build Coastguard Worker       Func->dump();
400*03ce13f7SAndroid Build Coastguard Worker       // Add a dummy work item as a placeholder.  This maintains sequence
401*03ce13f7SAndroid Build Coastguard Worker       // numbers so that the emitter thread will emit subsequent functions.
402*03ce13f7SAndroid Build Coastguard Worker       Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber());
403*03ce13f7SAndroid Build Coastguard Worker       emitQueueBlockingPush(std::move(Item));
404*03ce13f7SAndroid Build Coastguard Worker       continue; // Func goes out of scope and gets deleted
405*03ce13f7SAndroid Build Coastguard Worker     }
406*03ce13f7SAndroid Build Coastguard Worker 
407*03ce13f7SAndroid Build Coastguard Worker     Func->translate();
408*03ce13f7SAndroid Build Coastguard Worker     if (Func->hasError()) {
409*03ce13f7SAndroid Build Coastguard Worker       getErrorStatus()->assign(EC_Translation);
410*03ce13f7SAndroid Build Coastguard Worker       OstreamLocker L(this);
411*03ce13f7SAndroid Build Coastguard Worker       getStrError() << "ICE translation error: " << Func->getFunctionName()
412*03ce13f7SAndroid Build Coastguard Worker                     << ": " << Func->getError() << ": "
413*03ce13f7SAndroid Build Coastguard Worker                     << Func->getFunctionNameAndSize() << "\n";
414*03ce13f7SAndroid Build Coastguard Worker       Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber());
415*03ce13f7SAndroid Build Coastguard Worker     } else {
416*03ce13f7SAndroid Build Coastguard Worker       Func->getAssembler<>()->setInternal(Func->getInternal());
417*03ce13f7SAndroid Build Coastguard Worker       switch (getFlags().getOutFileType()) {
418*03ce13f7SAndroid Build Coastguard Worker       case FT_Elf:
419*03ce13f7SAndroid Build Coastguard Worker       case FT_Iasm: {
420*03ce13f7SAndroid Build Coastguard Worker         Func->emitIAS();
421*03ce13f7SAndroid Build Coastguard Worker         // The Cfg has already emitted into the assembly buffer, so
422*03ce13f7SAndroid Build Coastguard Worker         // stats have been fully collected into this thread's TLS.
423*03ce13f7SAndroid Build Coastguard Worker         // Dump them before TLS is reset for the next Cfg.
424*03ce13f7SAndroid Build Coastguard Worker         if (BuildDefs::dump())
425*03ce13f7SAndroid Build Coastguard Worker           dumpStats(Func.get());
426*03ce13f7SAndroid Build Coastguard Worker         auto Asm = Func->releaseAssembler();
427*03ce13f7SAndroid Build Coastguard Worker         // Copy relevant fields into Asm before Func is deleted.
428*03ce13f7SAndroid Build Coastguard Worker         Asm->setFunctionName(Func->getFunctionName());
429*03ce13f7SAndroid Build Coastguard Worker         Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
430*03ce13f7SAndroid Build Coastguard Worker                                            std::move(Asm));
431*03ce13f7SAndroid Build Coastguard Worker         Item->setGlobalInits(Func->getGlobalInits());
432*03ce13f7SAndroid Build Coastguard Worker       } break;
433*03ce13f7SAndroid Build Coastguard Worker       case FT_Asm:
434*03ce13f7SAndroid Build Coastguard Worker         // The Cfg has not been emitted yet, so stats are not ready
435*03ce13f7SAndroid Build Coastguard Worker         // to be dumped.
436*03ce13f7SAndroid Build Coastguard Worker         std::unique_ptr<VariableDeclarationList> GlobalInits =
437*03ce13f7SAndroid Build Coastguard Worker             Func->getGlobalInits();
438*03ce13f7SAndroid Build Coastguard Worker         Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
439*03ce13f7SAndroid Build Coastguard Worker                                            std::move(Func));
440*03ce13f7SAndroid Build Coastguard Worker         Item->setGlobalInits(std::move(GlobalInits));
441*03ce13f7SAndroid Build Coastguard Worker         break;
442*03ce13f7SAndroid Build Coastguard Worker       }
443*03ce13f7SAndroid Build Coastguard Worker     }
444*03ce13f7SAndroid Build Coastguard Worker     assert(Item != nullptr);
445*03ce13f7SAndroid Build Coastguard Worker     emitQueueBlockingPush(std::move(Item));
446*03ce13f7SAndroid Build Coastguard Worker     // The Cfg now gets deleted as Func goes out of scope.
447*03ce13f7SAndroid Build Coastguard Worker   }
448*03ce13f7SAndroid Build Coastguard Worker }
449*03ce13f7SAndroid Build Coastguard Worker 
450*03ce13f7SAndroid Build Coastguard Worker namespace {
451*03ce13f7SAndroid Build Coastguard Worker 
452*03ce13f7SAndroid Build Coastguard Worker // Ensure Pending is large enough that Pending[Index] is valid.
resizePending(std::vector<std::unique_ptr<EmitterWorkItem>> * Pending,uint32_t Index)453*03ce13f7SAndroid Build Coastguard Worker void resizePending(std::vector<std::unique_ptr<EmitterWorkItem>> *Pending,
454*03ce13f7SAndroid Build Coastguard Worker                    uint32_t Index) {
455*03ce13f7SAndroid Build Coastguard Worker   if (Index >= Pending->size())
456*03ce13f7SAndroid Build Coastguard Worker     Utils::reserveAndResize(*Pending, Index + 1);
457*03ce13f7SAndroid Build Coastguard Worker }
458*03ce13f7SAndroid Build Coastguard Worker 
459*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
460*03ce13f7SAndroid Build Coastguard Worker 
461*03ce13f7SAndroid Build Coastguard Worker // static
TlsInit()462*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::TlsInit() { ICE_TLS_INIT_FIELD(TLS); }
463*03ce13f7SAndroid Build Coastguard Worker 
emitFileHeader()464*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::emitFileHeader() {
465*03ce13f7SAndroid Build Coastguard Worker   TimerMarker T1(Ice::TimerStack::TT_emitAsm, this);
466*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().getOutFileType() == FT_Elf) {
467*03ce13f7SAndroid Build Coastguard Worker     getObjectWriter()->writeInitialELFHeader();
468*03ce13f7SAndroid Build Coastguard Worker   } else {
469*03ce13f7SAndroid Build Coastguard Worker     if (!BuildDefs::dump()) {
470*03ce13f7SAndroid Build Coastguard Worker       getStrError() << "emitFileHeader for non-ELF";
471*03ce13f7SAndroid Build Coastguard Worker       getErrorStatus()->assign(EC_Translation);
472*03ce13f7SAndroid Build Coastguard Worker     }
473*03ce13f7SAndroid Build Coastguard Worker     TargetHeaderLowering::createLowering(this)->lower();
474*03ce13f7SAndroid Build Coastguard Worker   }
475*03ce13f7SAndroid Build Coastguard Worker }
476*03ce13f7SAndroid Build Coastguard Worker 
lowerConstants()477*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
478*03ce13f7SAndroid Build Coastguard Worker 
lowerJumpTables()479*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::lowerJumpTables() { DataLowering->lowerJumpTables(); }
480*03ce13f7SAndroid Build Coastguard Worker 
emitTargetRODataSections()481*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::emitTargetRODataSections() {
482*03ce13f7SAndroid Build Coastguard Worker   DataLowering->emitTargetRODataSections();
483*03ce13f7SAndroid Build Coastguard Worker }
484*03ce13f7SAndroid Build Coastguard Worker 
lowerGlobals(const std::string & SectionSuffix)485*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::lowerGlobals(const std::string &SectionSuffix) {
486*03ce13f7SAndroid Build Coastguard Worker   TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
487*03ce13f7SAndroid Build Coastguard Worker   const bool DumpGlobalVariables =
488*03ce13f7SAndroid Build Coastguard Worker       BuildDefs::dump() && (getFlags().getVerbose() & IceV_GlobalInit) &&
489*03ce13f7SAndroid Build Coastguard Worker       getFlags().matchVerboseFocusOn("", 0);
490*03ce13f7SAndroid Build Coastguard Worker   if (DumpGlobalVariables) {
491*03ce13f7SAndroid Build Coastguard Worker     OstreamLocker L(this);
492*03ce13f7SAndroid Build Coastguard Worker     Ostream &Stream = getStrDump();
493*03ce13f7SAndroid Build Coastguard Worker     for (const Ice::VariableDeclaration *Global : Globals) {
494*03ce13f7SAndroid Build Coastguard Worker       Global->dump(Stream);
495*03ce13f7SAndroid Build Coastguard Worker     }
496*03ce13f7SAndroid Build Coastguard Worker   }
497*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().getDisableTranslation())
498*03ce13f7SAndroid Build Coastguard Worker     return;
499*03ce13f7SAndroid Build Coastguard Worker 
500*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::minimal() && Instrumentor)
501*03ce13f7SAndroid Build Coastguard Worker     Instrumentor->instrumentGlobals(Globals);
502*03ce13f7SAndroid Build Coastguard Worker 
503*03ce13f7SAndroid Build Coastguard Worker   DataLowering->lowerGlobals(Globals, SectionSuffix);
504*03ce13f7SAndroid Build Coastguard Worker   if (DisposeGlobalVariablesAfterLowering) {
505*03ce13f7SAndroid Build Coastguard Worker     Globals.clearAndPurge();
506*03ce13f7SAndroid Build Coastguard Worker   } else {
507*03ce13f7SAndroid Build Coastguard Worker     Globals.clear();
508*03ce13f7SAndroid Build Coastguard Worker   }
509*03ce13f7SAndroid Build Coastguard Worker }
510*03ce13f7SAndroid Build Coastguard Worker 
emitterWrapper(ThreadContext * MyTLS)511*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::emitterWrapper(ThreadContext *MyTLS) {
512*03ce13f7SAndroid Build Coastguard Worker   ICE_TLS_SET_FIELD(TLS, MyTLS);
513*03ce13f7SAndroid Build Coastguard Worker   emitItems();
514*03ce13f7SAndroid Build Coastguard Worker }
515*03ce13f7SAndroid Build Coastguard Worker 
emitItems()516*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::emitItems() {
517*03ce13f7SAndroid Build Coastguard Worker   const bool Threaded = !getFlags().isSequential();
518*03ce13f7SAndroid Build Coastguard Worker   // Pending is a vector containing the reassembled, ordered list of
519*03ce13f7SAndroid Build Coastguard Worker   // work items.  When we're ready for the next item, we first check
520*03ce13f7SAndroid Build Coastguard Worker   // whether it's in the Pending list.  If not, we take an item from
521*03ce13f7SAndroid Build Coastguard Worker   // the work queue, and if it's not the item we're waiting for, we
522*03ce13f7SAndroid Build Coastguard Worker   // insert it into Pending and repeat.  The work item is deleted
523*03ce13f7SAndroid Build Coastguard Worker   // after it is processed.
524*03ce13f7SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<EmitterWorkItem>> Pending;
525*03ce13f7SAndroid Build Coastguard Worker   uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
526*03ce13f7SAndroid Build Coastguard Worker   uint32_t ShuffleStartIndex = DesiredSequenceNumber;
527*03ce13f7SAndroid Build Coastguard Worker   uint32_t ShuffleEndIndex = DesiredSequenceNumber;
528*03ce13f7SAndroid Build Coastguard Worker   bool EmitQueueEmpty = false;
529*03ce13f7SAndroid Build Coastguard Worker 
530*03ce13f7SAndroid Build Coastguard Worker   while (!EmitQueueEmpty) {
531*03ce13f7SAndroid Build Coastguard Worker     resizePending(&Pending, DesiredSequenceNumber);
532*03ce13f7SAndroid Build Coastguard Worker     // See if Pending contains DesiredSequenceNumber.
533*03ce13f7SAndroid Build Coastguard Worker     if (Pending[DesiredSequenceNumber] == nullptr) {
534*03ce13f7SAndroid Build Coastguard Worker       // We need to fetch an EmitterWorkItem from the queue.
535*03ce13f7SAndroid Build Coastguard Worker       auto RawItem = emitQueueBlockingPop();
536*03ce13f7SAndroid Build Coastguard Worker       if (RawItem == nullptr) {
537*03ce13f7SAndroid Build Coastguard Worker         // This is the notifier for an empty queue.
538*03ce13f7SAndroid Build Coastguard Worker         EmitQueueEmpty = true;
539*03ce13f7SAndroid Build Coastguard Worker       } else {
540*03ce13f7SAndroid Build Coastguard Worker         // We get an EmitterWorkItem, we need to add it to Pending.
541*03ce13f7SAndroid Build Coastguard Worker         uint32_t ItemSeq = RawItem->getSequenceNumber();
542*03ce13f7SAndroid Build Coastguard Worker         if (Threaded && ItemSeq != DesiredSequenceNumber) {
543*03ce13f7SAndroid Build Coastguard Worker           // Not the desired one, add it to Pending but do not increase
544*03ce13f7SAndroid Build Coastguard Worker           // DesiredSequenceNumber. Continue the loop, do not emit the item.
545*03ce13f7SAndroid Build Coastguard Worker           resizePending(&Pending, ItemSeq);
546*03ce13f7SAndroid Build Coastguard Worker           Pending[ItemSeq] = std::move(RawItem);
547*03ce13f7SAndroid Build Coastguard Worker           continue;
548*03ce13f7SAndroid Build Coastguard Worker         }
549*03ce13f7SAndroid Build Coastguard Worker         // ItemSeq == DesiredSequenceNumber, we need to check if we should
550*03ce13f7SAndroid Build Coastguard Worker         // emit it or not. If !Threaded, we're OK with ItemSeq !=
551*03ce13f7SAndroid Build Coastguard Worker         // DesiredSequenceNumber.
552*03ce13f7SAndroid Build Coastguard Worker         Pending[DesiredSequenceNumber] = std::move(RawItem);
553*03ce13f7SAndroid Build Coastguard Worker       }
554*03ce13f7SAndroid Build Coastguard Worker     }
555*03ce13f7SAndroid Build Coastguard Worker 
556*03ce13f7SAndroid Build Coastguard Worker     // We have the desired EmitterWorkItem or nullptr as the end notifier.
557*03ce13f7SAndroid Build Coastguard Worker     // If the emitter queue is not empty, increase DesiredSequenceNumber and
558*03ce13f7SAndroid Build Coastguard Worker     // ShuffleEndIndex.
559*03ce13f7SAndroid Build Coastguard Worker     if (!EmitQueueEmpty) {
560*03ce13f7SAndroid Build Coastguard Worker       DesiredSequenceNumber++;
561*03ce13f7SAndroid Build Coastguard Worker       ShuffleEndIndex++;
562*03ce13f7SAndroid Build Coastguard Worker     }
563*03ce13f7SAndroid Build Coastguard Worker 
564*03ce13f7SAndroid Build Coastguard Worker     // Emit the item from ShuffleStartIndex to ShuffleEndIndex.
565*03ce13f7SAndroid Build Coastguard Worker     for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
566*03ce13f7SAndroid Build Coastguard Worker       std::unique_ptr<EmitterWorkItem> Item = std::move(Pending[I]);
567*03ce13f7SAndroid Build Coastguard Worker 
568*03ce13f7SAndroid Build Coastguard Worker       switch (Item->getKind()) {
569*03ce13f7SAndroid Build Coastguard Worker       case EmitterWorkItem::WI_Nop:
570*03ce13f7SAndroid Build Coastguard Worker         break;
571*03ce13f7SAndroid Build Coastguard Worker       case EmitterWorkItem::WI_GlobalInits: {
572*03ce13f7SAndroid Build Coastguard Worker         accumulateGlobals(Item->getGlobalInits());
573*03ce13f7SAndroid Build Coastguard Worker       } break;
574*03ce13f7SAndroid Build Coastguard Worker       case EmitterWorkItem::WI_Asm: {
575*03ce13f7SAndroid Build Coastguard Worker         lowerGlobalsIfNoCodeHasBeenSeen();
576*03ce13f7SAndroid Build Coastguard Worker         accumulateGlobals(Item->getGlobalInits());
577*03ce13f7SAndroid Build Coastguard Worker 
578*03ce13f7SAndroid Build Coastguard Worker         std::unique_ptr<Assembler> Asm = Item->getAsm();
579*03ce13f7SAndroid Build Coastguard Worker         Asm->alignFunction();
580*03ce13f7SAndroid Build Coastguard Worker         GlobalString Name = Asm->getFunctionName();
581*03ce13f7SAndroid Build Coastguard Worker         switch (getFlags().getOutFileType()) {
582*03ce13f7SAndroid Build Coastguard Worker         case FT_Elf:
583*03ce13f7SAndroid Build Coastguard Worker           getObjectWriter()->writeFunctionCode(Name, Asm->getInternal(),
584*03ce13f7SAndroid Build Coastguard Worker                                                Asm.get());
585*03ce13f7SAndroid Build Coastguard Worker           break;
586*03ce13f7SAndroid Build Coastguard Worker         case FT_Iasm: {
587*03ce13f7SAndroid Build Coastguard Worker           OstreamLocker L(this);
588*03ce13f7SAndroid Build Coastguard Worker           Cfg::emitTextHeader(Name, this, Asm.get());
589*03ce13f7SAndroid Build Coastguard Worker           Asm->emitIASBytes(this);
590*03ce13f7SAndroid Build Coastguard Worker         } break;
591*03ce13f7SAndroid Build Coastguard Worker         case FT_Asm:
592*03ce13f7SAndroid Build Coastguard Worker           llvm::report_fatal_error("Unexpected FT_Asm");
593*03ce13f7SAndroid Build Coastguard Worker           break;
594*03ce13f7SAndroid Build Coastguard Worker         }
595*03ce13f7SAndroid Build Coastguard Worker       } break;
596*03ce13f7SAndroid Build Coastguard Worker       case EmitterWorkItem::WI_Cfg: {
597*03ce13f7SAndroid Build Coastguard Worker         if (!BuildDefs::dump())
598*03ce13f7SAndroid Build Coastguard Worker           llvm::report_fatal_error("WI_Cfg work item created inappropriately");
599*03ce13f7SAndroid Build Coastguard Worker         lowerGlobalsIfNoCodeHasBeenSeen();
600*03ce13f7SAndroid Build Coastguard Worker         accumulateGlobals(Item->getGlobalInits());
601*03ce13f7SAndroid Build Coastguard Worker 
602*03ce13f7SAndroid Build Coastguard Worker         assert(getFlags().getOutFileType() == FT_Asm);
603*03ce13f7SAndroid Build Coastguard Worker         std::unique_ptr<Cfg> Func = Item->getCfg();
604*03ce13f7SAndroid Build Coastguard Worker         // Unfortunately, we have to temporarily install the Cfg in TLS
605*03ce13f7SAndroid Build Coastguard Worker         // because Variable::asType() uses the allocator to create the
606*03ce13f7SAndroid Build Coastguard Worker         // differently-typed copy.
607*03ce13f7SAndroid Build Coastguard Worker         CfgLocalAllocatorScope _(Func.get());
608*03ce13f7SAndroid Build Coastguard Worker         Func->emit();
609*03ce13f7SAndroid Build Coastguard Worker         dumpStats(Func.get());
610*03ce13f7SAndroid Build Coastguard Worker       } break;
611*03ce13f7SAndroid Build Coastguard Worker       }
612*03ce13f7SAndroid Build Coastguard Worker     }
613*03ce13f7SAndroid Build Coastguard Worker     // Update the start index for next shuffling queue
614*03ce13f7SAndroid Build Coastguard Worker     ShuffleStartIndex = ShuffleEndIndex;
615*03ce13f7SAndroid Build Coastguard Worker   }
616*03ce13f7SAndroid Build Coastguard Worker 
617*03ce13f7SAndroid Build Coastguard Worker   // In case there are no code to be generated, we invoke the conditional
618*03ce13f7SAndroid Build Coastguard Worker   // lowerGlobals again -- this is a no-op if code has been emitted.
619*03ce13f7SAndroid Build Coastguard Worker   lowerGlobalsIfNoCodeHasBeenSeen();
620*03ce13f7SAndroid Build Coastguard Worker }
621*03ce13f7SAndroid Build Coastguard Worker 
~GlobalContext()622*03ce13f7SAndroid Build Coastguard Worker GlobalContext::~GlobalContext() {
623*03ce13f7SAndroid Build Coastguard Worker   llvm::DeleteContainerPointers(AllThreadContexts);
624*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<DestructorArray> Dtors = getDestructors();
625*03ce13f7SAndroid Build Coastguard Worker   // Destructors are invoked in the opposite object construction order.
626*03ce13f7SAndroid Build Coastguard Worker   for (const auto &Dtor : reverse_range(*Dtors))
627*03ce13f7SAndroid Build Coastguard Worker     Dtor();
628*03ce13f7SAndroid Build Coastguard Worker }
629*03ce13f7SAndroid Build Coastguard Worker 
dumpStrings()630*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::dumpStrings() {
631*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStrings())
632*03ce13f7SAndroid Build Coastguard Worker     return;
633*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker _(this);
634*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = getStrDump();
635*03ce13f7SAndroid Build Coastguard Worker   Str << "GlobalContext strings:\n";
636*03ce13f7SAndroid Build Coastguard Worker   getStrings()->dump(Str);
637*03ce13f7SAndroid Build Coastguard Worker }
638*03ce13f7SAndroid Build Coastguard Worker 
dumpConstantLookupCounts()639*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::dumpConstantLookupCounts() {
640*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
641*03ce13f7SAndroid Build Coastguard Worker     return;
642*03ce13f7SAndroid Build Coastguard Worker   const bool DumpCounts = (getFlags().getVerbose() & IceV_ConstPoolStats) &&
643*03ce13f7SAndroid Build Coastguard Worker                           getFlags().matchVerboseFocusOn("", 0);
644*03ce13f7SAndroid Build Coastguard Worker   if (!DumpCounts)
645*03ce13f7SAndroid Build Coastguard Worker     return;
646*03ce13f7SAndroid Build Coastguard Worker 
647*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker _(this);
648*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = getStrDump();
649*03ce13f7SAndroid Build Coastguard Worker   Str << "Constant pool use stats: count+value+type\n";
650*03ce13f7SAndroid Build Coastguard Worker #define X(WhichPool)                                                           \
651*03ce13f7SAndroid Build Coastguard Worker   for (auto *C : getConstPool()->WhichPool.getConstantPool()) {                \
652*03ce13f7SAndroid Build Coastguard Worker     Str << C->getLookupCount() << " ";                                         \
653*03ce13f7SAndroid Build Coastguard Worker     C->dump(Str);                                                              \
654*03ce13f7SAndroid Build Coastguard Worker     Str << " " << C->getType() << "\n";                                        \
655*03ce13f7SAndroid Build Coastguard Worker   }
656*03ce13f7SAndroid Build Coastguard Worker   X(Integers1);
657*03ce13f7SAndroid Build Coastguard Worker   X(Integers8);
658*03ce13f7SAndroid Build Coastguard Worker   X(Integers16);
659*03ce13f7SAndroid Build Coastguard Worker   X(Integers32);
660*03ce13f7SAndroid Build Coastguard Worker   X(Integers64);
661*03ce13f7SAndroid Build Coastguard Worker   X(Floats);
662*03ce13f7SAndroid Build Coastguard Worker   X(Doubles);
663*03ce13f7SAndroid Build Coastguard Worker   X(Relocatables);
664*03ce13f7SAndroid Build Coastguard Worker   X(ExternRelocatables);
665*03ce13f7SAndroid Build Coastguard Worker #undef X
666*03ce13f7SAndroid Build Coastguard Worker }
667*03ce13f7SAndroid Build Coastguard Worker 
668*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): Consider adding thread-local caches of constant pool entries
669*03ce13f7SAndroid Build Coastguard Worker // to reduce contention.
670*03ce13f7SAndroid Build Coastguard Worker 
671*03ce13f7SAndroid Build Coastguard Worker // All locking is done by the getConstantInt[0-9]+() target function.
getConstantInt(Type Ty,int64_t Value)672*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
673*03ce13f7SAndroid Build Coastguard Worker   switch (Ty) {
674*03ce13f7SAndroid Build Coastguard Worker   case IceType_i1:
675*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt1(Value);
676*03ce13f7SAndroid Build Coastguard Worker   case IceType_i8:
677*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt8(Value);
678*03ce13f7SAndroid Build Coastguard Worker   case IceType_i16:
679*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt16(Value);
680*03ce13f7SAndroid Build Coastguard Worker   case IceType_i32:
681*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt32(Value);
682*03ce13f7SAndroid Build Coastguard Worker   case IceType_i64:
683*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt64(Value);
684*03ce13f7SAndroid Build Coastguard Worker   default:
685*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable("Bad integer type for getConstant");
686*03ce13f7SAndroid Build Coastguard Worker   }
687*03ce13f7SAndroid Build Coastguard Worker   return nullptr;
688*03ce13f7SAndroid Build Coastguard Worker }
689*03ce13f7SAndroid Build Coastguard Worker 
getConstantInt1Internal(int8_t ConstantInt1)690*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantInt1Internal(int8_t ConstantInt1) {
691*03ce13f7SAndroid Build Coastguard Worker   ConstantInt1 &= INT8_C(1);
692*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
693*03ce13f7SAndroid Build Coastguard Worker }
694*03ce13f7SAndroid Build Coastguard Worker 
getConstantInt8Internal(int8_t ConstantInt8)695*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantInt8Internal(int8_t ConstantInt8) {
696*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
697*03ce13f7SAndroid Build Coastguard Worker }
698*03ce13f7SAndroid Build Coastguard Worker 
getConstantInt16Internal(int16_t ConstantInt16)699*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantInt16Internal(int16_t ConstantInt16) {
700*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
701*03ce13f7SAndroid Build Coastguard Worker }
702*03ce13f7SAndroid Build Coastguard Worker 
getConstantInt32Internal(int32_t ConstantInt32)703*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantInt32Internal(int32_t ConstantInt32) {
704*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
705*03ce13f7SAndroid Build Coastguard Worker }
706*03ce13f7SAndroid Build Coastguard Worker 
getConstantInt64Internal(int64_t ConstantInt64)707*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantInt64Internal(int64_t ConstantInt64) {
708*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
709*03ce13f7SAndroid Build Coastguard Worker }
710*03ce13f7SAndroid Build Coastguard Worker 
getConstantFloat(float ConstantFloat)711*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
712*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Floats.getOrAdd(this, ConstantFloat);
713*03ce13f7SAndroid Build Coastguard Worker }
714*03ce13f7SAndroid Build Coastguard Worker 
getConstantDouble(double ConstantDouble)715*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
716*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Doubles.getOrAdd(this, ConstantDouble);
717*03ce13f7SAndroid Build Coastguard Worker }
718*03ce13f7SAndroid Build Coastguard Worker 
getConstantSymWithEmitString(const RelocOffsetT Offset,const RelocOffsetArray & OffsetExpr,GlobalString Name,const std::string & EmitString)719*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantSymWithEmitString(
720*03ce13f7SAndroid Build Coastguard Worker     const RelocOffsetT Offset, const RelocOffsetArray &OffsetExpr,
721*03ce13f7SAndroid Build Coastguard Worker     GlobalString Name, const std::string &EmitString) {
722*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Relocatables.getOrAdd(
723*03ce13f7SAndroid Build Coastguard Worker       this, RelocatableTuple(Offset, OffsetExpr, Name, EmitString));
724*03ce13f7SAndroid Build Coastguard Worker }
725*03ce13f7SAndroid Build Coastguard Worker 
getConstantSym(RelocOffsetT Offset,GlobalString Name)726*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
727*03ce13f7SAndroid Build Coastguard Worker                                         GlobalString Name) {
728*03ce13f7SAndroid Build Coastguard Worker   constexpr char EmptyEmitString[] = "";
729*03ce13f7SAndroid Build Coastguard Worker   return getConstantSymWithEmitString(Offset, {}, Name, EmptyEmitString);
730*03ce13f7SAndroid Build Coastguard Worker }
731*03ce13f7SAndroid Build Coastguard Worker 
getConstantExternSym(GlobalString Name)732*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantExternSym(GlobalString Name) {
733*03ce13f7SAndroid Build Coastguard Worker   constexpr RelocOffsetT Offset = 0;
734*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->ExternRelocatables.getOrAdd(
735*03ce13f7SAndroid Build Coastguard Worker       this, RelocatableTuple(Offset, {}, Name));
736*03ce13f7SAndroid Build Coastguard Worker }
737*03ce13f7SAndroid Build Coastguard Worker 
getConstantUndef(Type Ty)738*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantUndef(Type Ty) {
739*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->Undefs.getOrAdd(this, Ty);
740*03ce13f7SAndroid Build Coastguard Worker }
741*03ce13f7SAndroid Build Coastguard Worker 
getConstantZero(Type Ty)742*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantZero(Type Ty) {
743*03ce13f7SAndroid Build Coastguard Worker   Constant *Zero = ConstZeroForType[Ty];
744*03ce13f7SAndroid Build Coastguard Worker   if (Zero == nullptr)
745*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unsupported constant type: " + typeStdString(Ty));
746*03ce13f7SAndroid Build Coastguard Worker   return Zero;
747*03ce13f7SAndroid Build Coastguard Worker }
748*03ce13f7SAndroid Build Coastguard Worker 
749*03ce13f7SAndroid Build Coastguard Worker // All locking is done by the getConstant*() target function.
getConstantZeroInternal(Type Ty)750*03ce13f7SAndroid Build Coastguard Worker Constant *GlobalContext::getConstantZeroInternal(Type Ty) {
751*03ce13f7SAndroid Build Coastguard Worker   switch (Ty) {
752*03ce13f7SAndroid Build Coastguard Worker   case IceType_i1:
753*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt1Internal(0);
754*03ce13f7SAndroid Build Coastguard Worker   case IceType_i8:
755*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt8Internal(0);
756*03ce13f7SAndroid Build Coastguard Worker   case IceType_i16:
757*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt16Internal(0);
758*03ce13f7SAndroid Build Coastguard Worker   case IceType_i32:
759*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt32Internal(0);
760*03ce13f7SAndroid Build Coastguard Worker   case IceType_i64:
761*03ce13f7SAndroid Build Coastguard Worker     return getConstantInt64Internal(0);
762*03ce13f7SAndroid Build Coastguard Worker   case IceType_f32:
763*03ce13f7SAndroid Build Coastguard Worker     return getConstantFloat(0);
764*03ce13f7SAndroid Build Coastguard Worker   case IceType_f64:
765*03ce13f7SAndroid Build Coastguard Worker     return getConstantDouble(0);
766*03ce13f7SAndroid Build Coastguard Worker   default:
767*03ce13f7SAndroid Build Coastguard Worker     return nullptr;
768*03ce13f7SAndroid Build Coastguard Worker   }
769*03ce13f7SAndroid Build Coastguard Worker }
770*03ce13f7SAndroid Build Coastguard Worker 
getConstantPool(Type Ty)771*03ce13f7SAndroid Build Coastguard Worker ConstantList GlobalContext::getConstantPool(Type Ty) {
772*03ce13f7SAndroid Build Coastguard Worker   switch (Ty) {
773*03ce13f7SAndroid Build Coastguard Worker   case IceType_i1:
774*03ce13f7SAndroid Build Coastguard Worker   case IceType_i8:
775*03ce13f7SAndroid Build Coastguard Worker     return getConstPool()->Integers8.getConstantPool();
776*03ce13f7SAndroid Build Coastguard Worker   case IceType_i16:
777*03ce13f7SAndroid Build Coastguard Worker     return getConstPool()->Integers16.getConstantPool();
778*03ce13f7SAndroid Build Coastguard Worker   case IceType_i32:
779*03ce13f7SAndroid Build Coastguard Worker     return getConstPool()->Integers32.getConstantPool();
780*03ce13f7SAndroid Build Coastguard Worker   case IceType_i64:
781*03ce13f7SAndroid Build Coastguard Worker     return getConstPool()->Integers64.getConstantPool();
782*03ce13f7SAndroid Build Coastguard Worker   case IceType_f32:
783*03ce13f7SAndroid Build Coastguard Worker     return getConstPool()->Floats.getConstantPool();
784*03ce13f7SAndroid Build Coastguard Worker   case IceType_f64:
785*03ce13f7SAndroid Build Coastguard Worker     return getConstPool()->Doubles.getConstantPool();
786*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4i1:
787*03ce13f7SAndroid Build Coastguard Worker   case IceType_v8i1:
788*03ce13f7SAndroid Build Coastguard Worker   case IceType_v16i1:
789*03ce13f7SAndroid Build Coastguard Worker   case IceType_v16i8:
790*03ce13f7SAndroid Build Coastguard Worker   case IceType_v8i16:
791*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4i32:
792*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4f32:
793*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unsupported constant type: " + typeStdString(Ty));
794*03ce13f7SAndroid Build Coastguard Worker     break;
795*03ce13f7SAndroid Build Coastguard Worker   case IceType_void:
796*03ce13f7SAndroid Build Coastguard Worker   case IceType_NUM:
797*03ce13f7SAndroid Build Coastguard Worker     break;
798*03ce13f7SAndroid Build Coastguard Worker   }
799*03ce13f7SAndroid Build Coastguard Worker   llvm_unreachable("Unknown type");
800*03ce13f7SAndroid Build Coastguard Worker }
801*03ce13f7SAndroid Build Coastguard Worker 
getConstantExternSyms()802*03ce13f7SAndroid Build Coastguard Worker ConstantList GlobalContext::getConstantExternSyms() {
803*03ce13f7SAndroid Build Coastguard Worker   return getConstPool()->ExternRelocatables.getConstantPool();
804*03ce13f7SAndroid Build Coastguard Worker }
805*03ce13f7SAndroid Build Coastguard Worker 
getGlobalString(const std::string & Name)806*03ce13f7SAndroid Build Coastguard Worker GlobalString GlobalContext::getGlobalString(const std::string &Name) {
807*03ce13f7SAndroid Build Coastguard Worker   return GlobalString::createWithString(this, Name);
808*03ce13f7SAndroid Build Coastguard Worker }
809*03ce13f7SAndroid Build Coastguard Worker 
getJumpTables()810*03ce13f7SAndroid Build Coastguard Worker JumpTableDataList GlobalContext::getJumpTables() {
811*03ce13f7SAndroid Build Coastguard Worker   JumpTableDataList JumpTables(*getJumpTableList());
812*03ce13f7SAndroid Build Coastguard Worker   // Make order deterministic by sorting into functions and then ID of the jump
813*03ce13f7SAndroid Build Coastguard Worker   // table within that function.
814*03ce13f7SAndroid Build Coastguard Worker   std::sort(JumpTables.begin(), JumpTables.end(),
815*03ce13f7SAndroid Build Coastguard Worker             [](const JumpTableData &A, const JumpTableData &B) {
816*03ce13f7SAndroid Build Coastguard Worker               if (A.getFunctionName() != B.getFunctionName())
817*03ce13f7SAndroid Build Coastguard Worker                 return A.getFunctionName() < B.getFunctionName();
818*03ce13f7SAndroid Build Coastguard Worker               return A.getId() < B.getId();
819*03ce13f7SAndroid Build Coastguard Worker             });
820*03ce13f7SAndroid Build Coastguard Worker 
821*03ce13f7SAndroid Build Coastguard Worker   return JumpTables;
822*03ce13f7SAndroid Build Coastguard Worker }
823*03ce13f7SAndroid Build Coastguard Worker 
addJumpTableData(JumpTableData JumpTable)824*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::addJumpTableData(JumpTableData JumpTable) {
825*03ce13f7SAndroid Build Coastguard Worker   getJumpTableList()->emplace_back(std::move(JumpTable));
826*03ce13f7SAndroid Build Coastguard Worker }
827*03ce13f7SAndroid Build Coastguard Worker 
newTimerStackID(const std::string & Name)828*03ce13f7SAndroid Build Coastguard Worker TimerStackIdT GlobalContext::newTimerStackID(const std::string &Name) {
829*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::timers())
830*03ce13f7SAndroid Build Coastguard Worker     return 0;
831*03ce13f7SAndroid Build Coastguard Worker   auto Timers = getTimers();
832*03ce13f7SAndroid Build Coastguard Worker   TimerStackIdT NewID = Timers->size();
833*03ce13f7SAndroid Build Coastguard Worker   Timers->push_back(TimerStack(Name));
834*03ce13f7SAndroid Build Coastguard Worker   return NewID;
835*03ce13f7SAndroid Build Coastguard Worker }
836*03ce13f7SAndroid Build Coastguard Worker 
getTimerID(TimerStackIdT StackID,const std::string & Name)837*03ce13f7SAndroid Build Coastguard Worker TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
838*03ce13f7SAndroid Build Coastguard Worker                                    const std::string &Name) {
839*03ce13f7SAndroid Build Coastguard Worker   auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
840*03ce13f7SAndroid Build Coastguard Worker   assert(StackID < Timers->size());
841*03ce13f7SAndroid Build Coastguard Worker   return Timers->at(StackID).getTimerID(Name);
842*03ce13f7SAndroid Build Coastguard Worker }
843*03ce13f7SAndroid Build Coastguard Worker 
pushTimer(TimerIdT ID,TimerStackIdT StackID)844*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
845*03ce13f7SAndroid Build Coastguard Worker   auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
846*03ce13f7SAndroid Build Coastguard Worker   assert(StackID < Timers->size());
847*03ce13f7SAndroid Build Coastguard Worker   Timers->at(StackID).push(ID);
848*03ce13f7SAndroid Build Coastguard Worker }
849*03ce13f7SAndroid Build Coastguard Worker 
popTimer(TimerIdT ID,TimerStackIdT StackID)850*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
851*03ce13f7SAndroid Build Coastguard Worker   auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
852*03ce13f7SAndroid Build Coastguard Worker   assert(StackID < Timers->size());
853*03ce13f7SAndroid Build Coastguard Worker   Timers->at(StackID).pop(ID);
854*03ce13f7SAndroid Build Coastguard Worker }
855*03ce13f7SAndroid Build Coastguard Worker 
resetTimer(TimerStackIdT StackID)856*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::resetTimer(TimerStackIdT StackID) {
857*03ce13f7SAndroid Build Coastguard Worker   auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
858*03ce13f7SAndroid Build Coastguard Worker   assert(StackID < Timers->size());
859*03ce13f7SAndroid Build Coastguard Worker   Timers->at(StackID).reset();
860*03ce13f7SAndroid Build Coastguard Worker }
861*03ce13f7SAndroid Build Coastguard Worker 
getTimerName(TimerStackIdT StackID)862*03ce13f7SAndroid Build Coastguard Worker std::string GlobalContext::getTimerName(TimerStackIdT StackID) {
863*03ce13f7SAndroid Build Coastguard Worker   auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
864*03ce13f7SAndroid Build Coastguard Worker   assert(StackID < Timers->size());
865*03ce13f7SAndroid Build Coastguard Worker   return Timers->at(StackID).getName();
866*03ce13f7SAndroid Build Coastguard Worker }
867*03ce13f7SAndroid Build Coastguard Worker 
setTimerName(TimerStackIdT StackID,const std::string & NewName)868*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::setTimerName(TimerStackIdT StackID,
869*03ce13f7SAndroid Build Coastguard Worker                                  const std::string &NewName) {
870*03ce13f7SAndroid Build Coastguard Worker   auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
871*03ce13f7SAndroid Build Coastguard Worker   assert(StackID < Timers->size());
872*03ce13f7SAndroid Build Coastguard Worker   Timers->at(StackID).setName(NewName);
873*03ce13f7SAndroid Build Coastguard Worker }
874*03ce13f7SAndroid Build Coastguard Worker 
875*03ce13f7SAndroid Build Coastguard Worker // Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the
876*03ce13f7SAndroid Build Coastguard Worker // interface to take and transfer ownership, but they internally store the raw
877*03ce13f7SAndroid Build Coastguard Worker // Cfg pointer in the work queue. This allows e.g. future queue optimizations
878*03ce13f7SAndroid Build Coastguard Worker // such as the use of atomics to modify queue elements.
optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item)879*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item) {
880*03ce13f7SAndroid Build Coastguard Worker   assert(Item);
881*03ce13f7SAndroid Build Coastguard Worker   {
882*03ce13f7SAndroid Build Coastguard Worker     TimerMarker _(TimerStack::TT_qTransPush, this);
883*03ce13f7SAndroid Build Coastguard Worker     OptQ.blockingPush(std::move(Item));
884*03ce13f7SAndroid Build Coastguard Worker   }
885*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().isSequential())
886*03ce13f7SAndroid Build Coastguard Worker     translateFunctions();
887*03ce13f7SAndroid Build Coastguard Worker }
888*03ce13f7SAndroid Build Coastguard Worker 
optQueueBlockingPop()889*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<OptWorkItem> GlobalContext::optQueueBlockingPop() {
890*03ce13f7SAndroid Build Coastguard Worker   TimerMarker _(TimerStack::TT_qTransPop, this);
891*03ce13f7SAndroid Build Coastguard Worker   return OptQ.blockingPop(OptQWakeupSize);
892*03ce13f7SAndroid Build Coastguard Worker }
893*03ce13f7SAndroid Build Coastguard Worker 
emitQueueBlockingPush(std::unique_ptr<EmitterWorkItem> Item)894*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::emitQueueBlockingPush(
895*03ce13f7SAndroid Build Coastguard Worker     std::unique_ptr<EmitterWorkItem> Item) {
896*03ce13f7SAndroid Build Coastguard Worker   assert(Item);
897*03ce13f7SAndroid Build Coastguard Worker   {
898*03ce13f7SAndroid Build Coastguard Worker     TimerMarker _(TimerStack::TT_qEmitPush, this);
899*03ce13f7SAndroid Build Coastguard Worker     EmitQ.blockingPush(std::move(Item));
900*03ce13f7SAndroid Build Coastguard Worker   }
901*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().isSequential())
902*03ce13f7SAndroid Build Coastguard Worker     emitItems();
903*03ce13f7SAndroid Build Coastguard Worker }
904*03ce13f7SAndroid Build Coastguard Worker 
emitQueueBlockingPop()905*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<EmitterWorkItem> GlobalContext::emitQueueBlockingPop() {
906*03ce13f7SAndroid Build Coastguard Worker   TimerMarker _(TimerStack::TT_qEmitPop, this);
907*03ce13f7SAndroid Build Coastguard Worker   return EmitQ.blockingPop();
908*03ce13f7SAndroid Build Coastguard Worker }
909*03ce13f7SAndroid Build Coastguard Worker 
initParserThread()910*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::initParserThread() {
911*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *Tls = new ThreadContext();
912*03ce13f7SAndroid Build Coastguard Worker   auto Timers = getTimers();
913*03ce13f7SAndroid Build Coastguard Worker   Timers->initInto(Tls->Timers);
914*03ce13f7SAndroid Build Coastguard Worker   AllThreadContexts.push_back(Tls);
915*03ce13f7SAndroid Build Coastguard Worker   ICE_TLS_SET_FIELD(TLS, Tls);
916*03ce13f7SAndroid Build Coastguard Worker }
917*03ce13f7SAndroid Build Coastguard Worker 
startWorkerThreads()918*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::startWorkerThreads() {
919*03ce13f7SAndroid Build Coastguard Worker   size_t NumWorkers = getFlags().getNumTranslationThreads();
920*03ce13f7SAndroid Build Coastguard Worker   auto Timers = getTimers();
921*03ce13f7SAndroid Build Coastguard Worker   for (size_t i = 0; i < NumWorkers; ++i) {
922*03ce13f7SAndroid Build Coastguard Worker     ThreadContext *WorkerTLS = new ThreadContext();
923*03ce13f7SAndroid Build Coastguard Worker     Timers->initInto(WorkerTLS->Timers);
924*03ce13f7SAndroid Build Coastguard Worker     AllThreadContexts.push_back(WorkerTLS);
925*03ce13f7SAndroid Build Coastguard Worker     TranslationThreads.push_back(std::thread(
926*03ce13f7SAndroid Build Coastguard Worker         &GlobalContext::translateFunctionsWrapper, this, WorkerTLS));
927*03ce13f7SAndroid Build Coastguard Worker   }
928*03ce13f7SAndroid Build Coastguard Worker   if (NumWorkers) {
929*03ce13f7SAndroid Build Coastguard Worker     ThreadContext *WorkerTLS = new ThreadContext();
930*03ce13f7SAndroid Build Coastguard Worker     Timers->initInto(WorkerTLS->Timers);
931*03ce13f7SAndroid Build Coastguard Worker     AllThreadContexts.push_back(WorkerTLS);
932*03ce13f7SAndroid Build Coastguard Worker     EmitterThreads.push_back(
933*03ce13f7SAndroid Build Coastguard Worker         std::thread(&GlobalContext::emitterWrapper, this, WorkerTLS));
934*03ce13f7SAndroid Build Coastguard Worker   }
935*03ce13f7SAndroid Build Coastguard Worker }
936*03ce13f7SAndroid Build Coastguard Worker 
resetStats()937*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::resetStats() {
938*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::dump())
939*03ce13f7SAndroid Build Coastguard Worker     ICE_TLS_GET_FIELD(TLS)->StatsFunction.reset();
940*03ce13f7SAndroid Build Coastguard Worker }
941*03ce13f7SAndroid Build Coastguard Worker 
dumpStats(const Cfg * Func)942*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::dumpStats(const Cfg *Func) {
943*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStats())
944*03ce13f7SAndroid Build Coastguard Worker     return;
945*03ce13f7SAndroid Build Coastguard Worker   if (Func == nullptr) {
946*03ce13f7SAndroid Build Coastguard Worker     getStatsCumulative()->dump(Func, this);
947*03ce13f7SAndroid Build Coastguard Worker   } else {
948*03ce13f7SAndroid Build Coastguard Worker     ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Func, this);
949*03ce13f7SAndroid Build Coastguard Worker   }
950*03ce13f7SAndroid Build Coastguard Worker }
951*03ce13f7SAndroid Build Coastguard Worker 
statsUpdateEmitted(uint32_t InstCount)952*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::statsUpdateEmitted(uint32_t InstCount) {
953*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStats())
954*03ce13f7SAndroid Build Coastguard Worker     return;
955*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
956*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsFunction.update(CodeStats::CS_InstCount, InstCount);
957*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsCumulative.update(CodeStats::CS_InstCount, InstCount);
958*03ce13f7SAndroid Build Coastguard Worker }
959*03ce13f7SAndroid Build Coastguard Worker 
statsUpdateRegistersSaved(uint32_t Num)960*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::statsUpdateRegistersSaved(uint32_t Num) {
961*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStats())
962*03ce13f7SAndroid Build Coastguard Worker     return;
963*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
964*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsFunction.update(CodeStats::CS_RegsSaved, Num);
965*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsCumulative.update(CodeStats::CS_RegsSaved, Num);
966*03ce13f7SAndroid Build Coastguard Worker }
967*03ce13f7SAndroid Build Coastguard Worker 
statsUpdateFrameBytes(uint32_t Bytes)968*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::statsUpdateFrameBytes(uint32_t Bytes) {
969*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStats())
970*03ce13f7SAndroid Build Coastguard Worker     return;
971*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
972*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsFunction.update(CodeStats::CS_FrameByte, Bytes);
973*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsCumulative.update(CodeStats::CS_FrameByte, Bytes);
974*03ce13f7SAndroid Build Coastguard Worker }
975*03ce13f7SAndroid Build Coastguard Worker 
statsUpdateSpills()976*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::statsUpdateSpills() {
977*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStats())
978*03ce13f7SAndroid Build Coastguard Worker     return;
979*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
980*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsFunction.update(CodeStats::CS_NumSpills);
981*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsCumulative.update(CodeStats::CS_NumSpills);
982*03ce13f7SAndroid Build Coastguard Worker }
983*03ce13f7SAndroid Build Coastguard Worker 
statsUpdateFills()984*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::statsUpdateFills() {
985*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStats())
986*03ce13f7SAndroid Build Coastguard Worker     return;
987*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
988*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsFunction.update(CodeStats::CS_NumFills);
989*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsCumulative.update(CodeStats::CS_NumFills);
990*03ce13f7SAndroid Build Coastguard Worker }
991*03ce13f7SAndroid Build Coastguard Worker 
statsUpdateRPImms()992*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::statsUpdateRPImms() {
993*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getDumpStats())
994*03ce13f7SAndroid Build Coastguard Worker     return;
995*03ce13f7SAndroid Build Coastguard Worker   ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS);
996*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsFunction.update(CodeStats::CS_NumRPImms);
997*03ce13f7SAndroid Build Coastguard Worker   Tls->StatsCumulative.update(CodeStats::CS_NumRPImms);
998*03ce13f7SAndroid Build Coastguard Worker }
999*03ce13f7SAndroid Build Coastguard Worker 
dumpTimers(TimerStackIdT StackID,bool DumpCumulative)1000*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
1001*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::timers())
1002*03ce13f7SAndroid Build Coastguard Worker     return;
1003*03ce13f7SAndroid Build Coastguard Worker   auto Timers = getTimers();
1004*03ce13f7SAndroid Build Coastguard Worker   assert(Timers->size() > StackID);
1005*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker L(this);
1006*03ce13f7SAndroid Build Coastguard Worker   Timers->at(StackID).dump(getStrDump(), DumpCumulative);
1007*03ce13f7SAndroid Build Coastguard Worker }
1008*03ce13f7SAndroid Build Coastguard Worker 
dumpLocalTimers(const std::string & TimerNameOverride,TimerStackIdT StackID,bool DumpCumulative)1009*03ce13f7SAndroid Build Coastguard Worker void GlobalContext::dumpLocalTimers(const std::string &TimerNameOverride,
1010*03ce13f7SAndroid Build Coastguard Worker                                     TimerStackIdT StackID,
1011*03ce13f7SAndroid Build Coastguard Worker                                     bool DumpCumulative) {
1012*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::timers())
1013*03ce13f7SAndroid Build Coastguard Worker     return;
1014*03ce13f7SAndroid Build Coastguard Worker   auto *Timers = &ICE_TLS_GET_FIELD(TLS)->Timers;
1015*03ce13f7SAndroid Build Coastguard Worker   assert(Timers->size() > StackID);
1016*03ce13f7SAndroid Build Coastguard Worker   // Temporarily override the thread-local timer name with the given name.
1017*03ce13f7SAndroid Build Coastguard Worker   // Don't do it permanently because the final timer merge at the end expects
1018*03ce13f7SAndroid Build Coastguard Worker   // the thread-local timer names to be the same as the global timer name.
1019*03ce13f7SAndroid Build Coastguard Worker   auto OrigName = getTimerName(StackID);
1020*03ce13f7SAndroid Build Coastguard Worker   setTimerName(StackID, TimerNameOverride);
1021*03ce13f7SAndroid Build Coastguard Worker   {
1022*03ce13f7SAndroid Build Coastguard Worker     OstreamLocker _(this);
1023*03ce13f7SAndroid Build Coastguard Worker     Timers->at(StackID).dump(getStrDump(), DumpCumulative);
1024*03ce13f7SAndroid Build Coastguard Worker   }
1025*03ce13f7SAndroid Build Coastguard Worker   setTimerName(StackID, OrigName);
1026*03ce13f7SAndroid Build Coastguard Worker }
1027*03ce13f7SAndroid Build Coastguard Worker 
1028*03ce13f7SAndroid Build Coastguard Worker LockedPtr<StringPool>
getStrings(const GlobalContext * PoolOwner)1029*03ce13f7SAndroid Build Coastguard Worker GlobalStringPoolTraits::getStrings(const GlobalContext *PoolOwner) {
1030*03ce13f7SAndroid Build Coastguard Worker   return PoolOwner->getStrings();
1031*03ce13f7SAndroid Build Coastguard Worker }
1032*03ce13f7SAndroid Build Coastguard Worker 
getTimerIdFromFuncName(GlobalContext * Ctx,const std::string & FuncName)1033*03ce13f7SAndroid Build Coastguard Worker TimerIdT TimerMarker::getTimerIdFromFuncName(GlobalContext *Ctx,
1034*03ce13f7SAndroid Build Coastguard Worker                                              const std::string &FuncName) {
1035*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::timers())
1036*03ce13f7SAndroid Build Coastguard Worker     return 0;
1037*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getTimeEachFunction())
1038*03ce13f7SAndroid Build Coastguard Worker     return 0;
1039*03ce13f7SAndroid Build Coastguard Worker   return Ctx->getTimerID(GlobalContext::TSK_Funcs, FuncName);
1040*03ce13f7SAndroid Build Coastguard Worker }
1041*03ce13f7SAndroid Build Coastguard Worker 
push()1042*03ce13f7SAndroid Build Coastguard Worker void TimerMarker::push() {
1043*03ce13f7SAndroid Build Coastguard Worker   switch (StackID) {
1044*03ce13f7SAndroid Build Coastguard Worker   case GlobalContext::TSK_Default:
1045*03ce13f7SAndroid Build Coastguard Worker     Active = getFlags().getSubzeroTimingEnabled() ||
1046*03ce13f7SAndroid Build Coastguard Worker              !getFlags().getTimingFocusOnString().empty();
1047*03ce13f7SAndroid Build Coastguard Worker     break;
1048*03ce13f7SAndroid Build Coastguard Worker   case GlobalContext::TSK_Funcs:
1049*03ce13f7SAndroid Build Coastguard Worker     Active = getFlags().getTimeEachFunction();
1050*03ce13f7SAndroid Build Coastguard Worker     break;
1051*03ce13f7SAndroid Build Coastguard Worker   default:
1052*03ce13f7SAndroid Build Coastguard Worker     break;
1053*03ce13f7SAndroid Build Coastguard Worker   }
1054*03ce13f7SAndroid Build Coastguard Worker   if (Active)
1055*03ce13f7SAndroid Build Coastguard Worker     Ctx->pushTimer(ID, StackID);
1056*03ce13f7SAndroid Build Coastguard Worker }
1057*03ce13f7SAndroid Build Coastguard Worker 
pushCfg(const Cfg * Func)1058*03ce13f7SAndroid Build Coastguard Worker void TimerMarker::pushCfg(const Cfg *Func) {
1059*03ce13f7SAndroid Build Coastguard Worker   Ctx = Func->getContext();
1060*03ce13f7SAndroid Build Coastguard Worker   Active = Func->getFocusedTiming() || getFlags().getSubzeroTimingEnabled();
1061*03ce13f7SAndroid Build Coastguard Worker   if (Active)
1062*03ce13f7SAndroid Build Coastguard Worker     Ctx->pushTimer(ID, StackID);
1063*03ce13f7SAndroid Build Coastguard Worker }
1064*03ce13f7SAndroid Build Coastguard Worker 
1065*03ce13f7SAndroid Build Coastguard Worker ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
1066*03ce13f7SAndroid Build Coastguard Worker 
1067*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1068