blob: 3e6519a5f1fdb063d07d5c85fa5af8be23699fb5 [file] [log] [blame]
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001//===- subzero/src/IceDefs.h - Common Subzero declarations ------*- C++ -*-===//
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 Declares various useful types and classes that have widespread use
12/// across Subzero.
13///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070014//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICEDEFS_H
17#define SUBZERO_SRC_ICEDEFS_H
18
John Porto67f8de92015-06-25 10:14:17 -070019#include "IceBuildDefs.h" // TODO(stichnot): move into individual files
John Portoe82b5602016-02-24 15:58:55 -080020#include "IceMemory.h"
John Porto67f8de92015-06-25 10:14:17 -070021#include "IceTLS.h"
22
Jan Voungb17f61d2014-08-28 16:00:53 -070023#include "llvm/ADT/ArrayRef.h"
Jim Stichnoth607e9f02014-11-06 13:32:05 -080024#include "llvm/ADT/ilist.h"
25#include "llvm/ADT/ilist_node.h"
Jim Stichnoth7e571362015-01-09 11:43:26 -080026#include "llvm/ADT/iterator_range.h"
Jim Stichnoth586d4c22014-12-05 16:43:08 -080027#include "llvm/ADT/SmallVector.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070028#include "llvm/ADT/STLExtras.h"
29#include "llvm/Support/Casting.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080030#include "llvm/Support/ELF.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070031#include "llvm/Support/raw_ostream.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070032
John Porto67f8de92015-06-25 10:14:17 -070033#include <cassert>
34#include <cstdint>
35#include <cstdio> // snprintf
36#include <functional> // std::less
37#include <limits>
38#include <list>
39#include <map>
40#include <memory>
41#include <mutex>
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -070042#include <set>
John Porto67f8de92015-06-25 10:14:17 -070043#include <string>
44#include <system_error>
Karl Schimpfac7d7342015-08-06 12:55:23 -070045#include <unordered_map>
John Portoe82b5602016-02-24 15:58:55 -080046#include <unordered_set>
47#include <utility>
John Porto67f8de92015-06-25 10:14:17 -070048#include <vector>
Jim Stichnoth7d538252015-01-23 10:22:56 -080049
Jim Stichnoth84ea9a72016-09-09 09:33:07 -070050#define XSTRINGIFY(x) STRINGIFY(x)
51#define STRINGIFY(x) #x
52
Jim Stichnothf7c9a142014-04-29 10:52:43 -070053namespace Ice {
54
Jan Voungec270732015-01-12 17:00:22 -080055class Assembler;
John Porto7bb9cab2016-04-01 05:43:09 -070056template <template <typename> class> class BitVectorTmpl;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070057class Cfg;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058class CfgNode;
59class Constant;
Nicolas Capens3e376472016-09-13 11:35:57 -040060class ELFFileStreamer;
Jan Voungec270732015-01-12 17:00:22 -080061class ELFObjectWriter;
62class ELFStreamer;
Karl Schimpf9d98d792014-10-13 15:01:08 -070063class FunctionDeclaration;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070064class GlobalContext;
Karl Schimpf9d98d792014-10-13 15:01:08 -070065class GlobalDeclaration;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070066class Inst;
Jim Stichnoth336f6c42014-10-30 15:01:31 -070067class InstAssign;
Andrew Scull86df4e92015-07-30 13:54:44 -070068class InstJumpTable;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070069class InstPhi;
Andrew Scull86df4e92015-07-30 13:54:44 -070070class InstSwitch;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070071class InstTarget;
Jim Stichnothd97c7df2014-06-04 11:57:08 -070072class LiveRange;
73class Liveness;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070074class Operand;
Jan Voung72984d82015-01-29 14:42:38 -080075class TargetDataLowering;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070076class TargetLowering;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070077class Variable;
Karl Schimpf9d98d792014-10-13 15:01:08 -070078class VariableDeclaration;
Jim Stichnoth144cdce2014-09-22 16:02:59 -070079class VariablesMetadata;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070080
John Portoa78e4ba2016-03-15 09:28:04 -070081/// SizeT is for holding small-ish limits like number of source operands in an
82/// instruction. It is used instead of size_t (which may be 64-bits wide) when
83/// we want to save space.
84using SizeT = uint32_t;
85
John Porto6e8d3fa2016-02-04 10:35:20 -080086constexpr char GlobalOffsetTable[] = "_GLOBAL_OFFSET_TABLE_";
John Porto1bec8bc2015-06-22 10:51:13 -070087// makeUnique should be used when memory is expected to be allocated from the
Andrew Scull57e12682015-09-16 11:30:19 -070088// heap (as opposed to allocated from some Allocator.) It is intended to be
89// used instead of new.
John Porto1bec8bc2015-06-22 10:51:13 -070090//
91// The expected usage is as follows
92//
93// class MyClass {
94// public:
95// static std::unique_ptr<MyClass> create(<ctor_args>) {
96// return makeUnique<MyClass>(<ctor_args>);
97// }
98//
99// private:
100// ENABLE_MAKE_UNIQUE;
101//
102// MyClass(<ctor_args>) ...
103// }
104//
105// ENABLE_MAKE_UNIQUE is a trick that is necessary if MyClass' ctor is private.
106// Private ctors are highly encouraged when you're writing a class that you'd
107// like to have allocated with makeUnique as it would prevent users from
108// declaring stack allocated variables.
109namespace Internal {
110struct MakeUniqueEnabler {
111 template <class T, class... Args>
112 static std::unique_ptr<T> create(Args &&... TheArgs) {
113 std::unique_ptr<T> Unique(new T(std::forward<Args>(TheArgs)...));
114 return Unique;
115 }
116};
117} // end of namespace Internal
118
119template <class T, class... Args>
120static std::unique_ptr<T> makeUnique(Args &&... TheArgs) {
121 return ::Ice::Internal::MakeUniqueEnabler::create<T>(
122 std::forward<Args>(TheArgs)...);
123}
124
125#define ENABLE_MAKE_UNIQUE friend struct ::Ice::Internal::MakeUniqueEnabler
126
Andrew Scull8072bae2015-09-14 16:01:26 -0700127using InstList = llvm::ilist<Inst>;
Andrew Scull57e12682015-09-16 11:30:19 -0700128// Ideally PhiList would be llvm::ilist<InstPhi>, and similar for AssignList,
129// but this runs into issues with SFINAE.
Andrew Scull8072bae2015-09-14 16:01:26 -0700130using PhiList = InstList;
131using AssignList = InstList;
Karl Schimpf209318a2015-08-20 13:24:02 -0700132
Andrew Scull00741a02015-09-16 19:04:09 -0700133// Standard library containers with CfgLocalAllocator.
Andrew Scull00741a02015-09-16 19:04:09 -0700134template <typename T> using CfgList = std::list<T, CfgLocalAllocator<T>>;
John Portoe82b5602016-02-24 15:58:55 -0800135template <typename T, typename H = std::hash<T>, typename Eq = std::equal_to<T>>
136using CfgUnorderedSet = std::unordered_set<T, H, Eq, CfgLocalAllocator<T>>;
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700137template <typename T, typename Cmp = std::less<T>>
138using CfgSet = std::set<T, Cmp, CfgLocalAllocator<T>>;
John Portoe82b5602016-02-24 15:58:55 -0800139template <typename T, typename U, typename H = std::hash<T>,
140 typename Eq = std::equal_to<T>>
141using CfgUnorderedMap =
142 std::unordered_map<T, U, H, Eq, CfgLocalAllocator<std::pair<const T, U>>>;
143template <typename T> using CfgVector = std::vector<T, CfgLocalAllocator<T>>;
Andrew Scull00741a02015-09-16 19:04:09 -0700144
Karl Schimpf209318a2015-08-20 13:24:02 -0700145// Containers that are arena-allocated from the Cfg's allocator.
Andrew Scull00741a02015-09-16 19:04:09 -0700146using OperandList = CfgVector<Operand *>;
147using VarList = CfgVector<Variable *>;
148using NodeList = CfgVector<CfgNode *>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700149
John Portoe82b5602016-02-24 15:58:55 -0800150// Containers that use the default (global) allocator.
Andrew Scull8072bae2015-09-14 16:01:26 -0700151using ConstantList = std::vector<Constant *>;
152using FunctionDeclarationList = std::vector<FunctionDeclaration *>;
Jan Voung72984d82015-01-29 14:42:38 -0800153
John Portoa78e4ba2016-03-15 09:28:04 -0700154/// VariableDeclarationList is a container for holding VariableDeclarations --
155/// i.e., Global Variables. It is also used to create said variables, and their
156/// initializers in an arena.
157class VariableDeclarationList {
158 VariableDeclarationList(const VariableDeclarationList &) = delete;
159 VariableDeclarationList &operator=(const VariableDeclarationList &) = delete;
160 VariableDeclarationList(VariableDeclarationList &&) = delete;
161 VariableDeclarationList &operator=(VariableDeclarationList &&) = delete;
162
163public:
164 using VariableDeclarationArray = std::vector<VariableDeclaration *>;
165
166 VariableDeclarationList() : Arena(new ArenaAllocator()) {}
167
168 ~VariableDeclarationList() { clearAndPurge(); }
169
170 template <typename T> T *allocate_initializer(SizeT Count = 1) {
171 static_assert(
172 std::is_trivially_destructible<T>::value,
173 "allocate_initializer can only allocate trivially destructible types.");
174 return Arena->Allocate<T>(Count);
175 }
176
177 template <typename T> T *allocate_variable_declaration() {
178 static_assert(!std::is_trivially_destructible<T>::value,
179 "allocate_variable_declaration expects non-trivially "
180 "destructible types.");
181 T *Ret = Arena->Allocate<T>();
182 Dtors.emplace_back([Ret]() { Ret->~T(); });
183 return Ret;
184 }
185
186 // This do nothing method is invoked when a global variable is created, but it
Thomas Lively3f5cb6f2016-06-13 11:23:29 -0700187 // will not be emitted. If we ever need to track the created variable, having
John Portoa78e4ba2016-03-15 09:28:04 -0700188 // this hook is handy.
189 void willNotBeEmitted(VariableDeclaration *) {}
190
191 /// Merges Other with this, effectively resetting Other to an empty state.
192 void merge(VariableDeclarationList *Other) {
193 assert(Other != nullptr);
194 addArena(std::move(Other->Arena));
195 for (std::size_t i = 0; i < Other->MergedArenas.size(); ++i) {
196 addArena(std::move(Other->MergedArenas[i]));
197 }
198 Other->MergedArenas.clear();
199
200 Dtors.insert(Dtors.end(), Other->Dtors.begin(), Other->Dtors.end());
201 Other->Dtors.clear();
202
203 Globals.insert(Globals.end(), Other->Globals.begin(), Other->Globals.end());
204 Other->Globals.clear();
205 }
206
207 /// Destroys all GlobalVariables and initializers that this knows about
208 /// (including those merged with it), and releases memory.
209 void clearAndPurge() {
210 if (Arena == nullptr) {
211 // Arena is only null if this was merged, so we ensure there's no state
212 // being held by this.
213 assert(Dtors.empty());
214 assert(Globals.empty());
215 assert(MergedArenas.empty());
216 return;
217 }
218 // Invokes destructors in reverse creation order.
219 for (auto Dtor = Dtors.rbegin(); Dtor != Dtors.rend(); ++Dtor) {
220 (*Dtor)();
221 }
222 Dtors.clear();
223 Globals.clear();
224 MergedArenas.clear();
225 Arena->Reset();
226 }
227
228 /// Adapt the relevant parts of the std::vector<VariableDeclaration *>
229 /// interface.
230 /// @{
231 VariableDeclarationArray::iterator begin() { return Globals.begin(); }
232
233 VariableDeclarationArray::iterator end() { return Globals.end(); }
234
235 VariableDeclarationArray::const_iterator begin() const {
236 return Globals.begin();
237 }
238
239 VariableDeclarationArray::const_iterator end() const { return Globals.end(); }
240
241 bool empty() const { return Globals.empty(); }
242
243 VariableDeclarationArray::size_type size() const { return Globals.size(); }
244
245 VariableDeclarationArray::reference
246 at(VariableDeclarationArray::size_type Pos) {
247 return Globals.at(Pos);
248 }
249
250 void push_back(VariableDeclaration *Global) { Globals.push_back(Global); }
251
252 void reserve(VariableDeclarationArray::size_type Capacity) {
253 Globals.reserve(Capacity);
254 }
255
256 void clear() { Globals.clear(); }
257
258 VariableDeclarationArray::reference back() { return Globals.back(); }
259 /// @}
260
261private:
262 using ArenaPtr = std::unique_ptr<ArenaAllocator>;
263 using DestructorsArray = std::vector<std::function<void()>>;
264
265 void addArena(ArenaPtr NewArena) {
266 MergedArenas.emplace_back(std::move(NewArena));
267 }
268
269 ArenaPtr Arena;
270 VariableDeclarationArray Globals;
271 DestructorsArray Dtors;
272 std::vector<ArenaPtr> MergedArenas;
273};
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700274
Andrew Scull57e12682015-09-16 11:30:19 -0700275/// InstNumberT is for holding an instruction number. Instruction numbers are
276/// used for representing Variable live ranges.
Andrew Scull8072bae2015-09-14 16:01:26 -0700277using InstNumberT = int32_t;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700278
Andrew Scull57e12682015-09-16 11:30:19 -0700279/// A LiveBeginEndMapEntry maps a Variable::Number value to an Inst::Number
280/// value, giving the instruction number that begins or ends a variable's live
281/// range.
John Porto7bb9cab2016-04-01 05:43:09 -0700282template <typename T>
283using LivenessVector = std::vector<T, LivenessAllocator<T>>;
Andrew Scull8072bae2015-09-14 16:01:26 -0700284using LiveBeginEndMapEntry = std::pair<SizeT, InstNumberT>;
John Porto7bb9cab2016-04-01 05:43:09 -0700285using LiveBeginEndMap = LivenessVector<LiveBeginEndMapEntry>;
286using LivenessBV = BitVectorTmpl<LivenessAllocator>;
Jim Stichnoth47752552014-10-13 17:15:08 -0700287
Andrew Scull8072bae2015-09-14 16:01:26 -0700288using TimerStackIdT = uint32_t;
289using TimerIdT = uint32_t;
Jim Stichnothc4554d72014-09-30 16:49:38 -0700290
Andrew Scull57e12682015-09-16 11:30:19 -0700291/// Use alignas(MaxCacheLineSize) to isolate variables/fields that might be
292/// contended while multithreading. Assumes the maximum cache line size is 64.
Jim Stichnothdd842db2015-01-27 12:53:53 -0800293enum { MaxCacheLineSize = 64 };
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800294// Use ICE_CACHELINE_BOUNDARY to force the next field in a declaration
295// list to be aligned to the next cache line.
Nicolas Capensd5e7caf2016-09-01 11:40:49 -0400296#if defined(_MSC_VER)
297#define ICE_CACHELINE_BOUNDARY __declspec(align(MaxCacheLineSize)) int : 0;
298#else // !defined(_MSC_VER)
JF Bastien867684e2015-01-28 15:07:38 -0800299// Note: zero is added to work around the following GCC 4.8 bug (fixed in 4.9):
300// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55382
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800301#define ICE_CACHELINE_BOUNDARY \
JF Bastien867684e2015-01-28 15:07:38 -0800302 __attribute__((aligned(MaxCacheLineSize + 0))) int : 0
Nicolas Capensd5e7caf2016-09-01 11:40:49 -0400303#endif // !defined(_MSC_VER)
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800304
Andrew Scull9612d322015-07-06 14:53:25 -0700305/// PNaCl is ILP32, so theoretically we should only need 32-bit offsets.
Andrew Scull8072bae2015-09-14 16:01:26 -0700306using RelocOffsetT = int32_t;
Jan Voungc0d965f2014-11-04 16:55:01 -0800307enum { RelocAddrSize = 4 };
Jan Voungfe14fb82014-10-13 15:56:32 -0700308
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700309enum LivenessMode {
Andrew Scull57e12682015-09-16 11:30:19 -0700310 /// Basic version of live-range-end calculation. Marks the last uses of
311 /// variables based on dataflow analysis. Records the set of live-in and
312 /// live-out variables for each block. Identifies and deletes dead
313 /// instructions (primarily stores).
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700314 Liveness_Basic,
315
Andrew Scull57e12682015-09-16 11:30:19 -0700316 /// In addition to Liveness_Basic, also calculate the complete live range for
317 /// each variable in a form suitable for interference calculation and register
318 /// allocation.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700319 Liveness_Intervals
320};
321
Manasij Mukherjee53c8fbd2016-08-01 15:40:42 -0700322enum LCSEOptions {
323 LCSE_Disabled,
324 LCSE_EnabledSSA, // Default Mode, assumes SSA.
325 LCSE_EnabledNoSSA // Does not assume SSA, to be enabled if CSE is done later.
326};
327
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800328enum RegAllocKind {
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700329 RAK_Unknown,
Jim Stichnoth4001c932015-10-09 14:33:26 -0700330 RAK_Global, /// full, global register allocation
331 RAK_SecondChance, /// second-chance bin-packing after full regalloc attempt
332 RAK_Phi, /// infinite-weight Variables with active spilling/filling
333 RAK_InfOnly /// allocation only for infinite-weight Variables
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800334};
335
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700336enum VerboseItem {
337 IceV_None = 0,
338 IceV_Instructions = 1 << 0,
339 IceV_Deleted = 1 << 1,
340 IceV_InstNumbers = 1 << 2,
341 IceV_Preds = 1 << 3,
342 IceV_Succs = 1 << 4,
343 IceV_Liveness = 1 << 5,
Jim Stichnoth769be682015-01-15 09:05:08 -0800344 IceV_RegOrigins = 1 << 6,
345 IceV_LinearScan = 1 << 7,
346 IceV_Frame = 1 << 8,
347 IceV_AddrOpt = 1 << 9,
348 IceV_Random = 1 << 10,
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700349 IceV_Folding = 1 << 11,
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700350 IceV_RMW = 1 << 12,
Andrew Scullaa6c1092015-09-03 17:50:30 -0700351 IceV_Loop = 1 << 13,
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800352 IceV_Mem = 1 << 14,
353 // Leave some extra space to make it easier to add new per-pass items.
354 IceV_NO_PER_PASS_DUMP_BEYOND = 1 << 19,
355 // Items greater than IceV_NO_PER_PASS_DUMP_BEYOND don't by themselves trigger
356 // per-pass Cfg dump output.
357 IceV_Status = 1 << 20,
358 IceV_AvailableRegs = 1 << 21,
359 IceV_GlobalInit = 1 << 22,
360 IceV_ConstPoolStats = 1 << 23,
Eric Holk16f80612016-04-04 17:07:42 -0700361 IceV_Wasm = 1 << 24,
John Portoa47c11c2016-04-21 05:53:42 -0700362 IceV_ShufMat = 1 << 25,
Jim Stichnothad403532014-09-25 12:44:17 -0700363 IceV_All = ~IceV_None,
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800364 IceV_Most =
Jim Stichnoth76719b42016-03-14 08:37:52 -0700365 IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit & ~IceV_ConstPoolStats
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700366};
Andrew Scull8072bae2015-09-14 16:01:26 -0700367using VerboseMask = uint32_t;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700368
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800369enum FileType {
Andrew Scull9612d322015-07-06 14:53:25 -0700370 FT_Elf, /// ELF .o file
371 FT_Asm, /// Assembly .s file
372 FT_Iasm /// "Integrated assembler" .byte-style .s file
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800373};
374
Nicolas Capens41ce47c2016-09-16 17:00:12 -0400375enum ABI {
376 ABI_PNaCl, /// x32 for unsandboxed 64-bit x86
377 ABI_Platform /// Native executable ABI
378};
379
Andrew Scull8072bae2015-09-14 16:01:26 -0700380using Ostream = llvm::raw_ostream;
381using Fdstream = llvm::raw_fd_ostream;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700382
Andrew Scull8072bae2015-09-14 16:01:26 -0700383using GlobalLockType = std::mutex;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800384
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700385/// LockedPtr is an RAII wrapper that allows automatically locked access to a
386/// given pointer, automatically unlocking it when when the LockedPtr goes out
387/// of scope.
388template <typename T> class LockedPtr {
389 LockedPtr() = delete;
390 LockedPtr(const LockedPtr &) = delete;
391 LockedPtr &operator=(const LockedPtr &) = delete;
392
393public:
394 LockedPtr(T *Value, GlobalLockType *Lock) : Value(Value), Lock(Lock) {
395 Lock->lock();
396 }
397 LockedPtr(LockedPtr &&Other) : Value(Other.Value), Lock(Other.Lock) {
398 Other.Value = nullptr;
399 Other.Lock = nullptr;
400 }
Nicolas Capens6c629dc2017-04-25 16:41:00 -0400401 ~LockedPtr() {
402 if (Lock != nullptr)
403 Lock->unlock();
404 }
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700405 T *operator->() const { return Value; }
406 T &operator*() const { return *Value; }
407 T *get() { return Value; }
408
409private:
410 T *Value;
411 GlobalLockType *Lock;
412};
413
Jim Stichnothdd842db2015-01-27 12:53:53 -0800414enum ErrorCodes { EC_None = 0, EC_Args, EC_Bitcode, EC_Translation };
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800415
Andrew Scull57e12682015-09-16 11:30:19 -0700416/// Wrapper around std::error_code for allowing multiple errors to be folded
417/// into one. The current implementation keeps track of the first error, which
418/// is likely to be the most useful one, and this could be extended to e.g.
419/// collect a vector of errors.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800420class ErrorCode : public std::error_code {
421 ErrorCode(const ErrorCode &) = delete;
422 ErrorCode &operator=(const ErrorCode &) = delete;
423
424public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700425 ErrorCode() = default;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800426 void assign(ErrorCodes Code) {
427 if (!HasError) {
428 HasError = true;
429 std::error_code::assign(Code, std::generic_category());
430 }
431 }
432 void assign(int Code) { assign(static_cast<ErrorCodes>(Code)); }
433
434private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700435 bool HasError = false;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800436};
437
Andrew Scull9612d322015-07-06 14:53:25 -0700438/// Reverse range adaptors written in terms of llvm::make_range().
Jim Stichnoth7e571362015-01-09 11:43:26 -0800439template <typename T>
440llvm::iterator_range<typename T::const_reverse_iterator>
441reverse_range(const T &Container) {
442 return llvm::make_range(Container.rbegin(), Container.rend());
443}
444template <typename T>
445llvm::iterator_range<typename T::reverse_iterator> reverse_range(T &Container) {
446 return llvm::make_range(Container.rbegin(), Container.rend());
447}
448
Andrew Scull9612d322015-07-06 14:53:25 -0700449/// Options for pooling and randomization of immediates.
Qining Lu253dc8a2015-06-22 10:10:23 -0700450enum RandomizeAndPoolImmediatesEnum { RPI_None, RPI_Randomize, RPI_Pool };
451
Qining Luaee5fa82015-08-20 14:59:03 -0700452/// Salts for Random number generator for different randomization passes.
453enum RandomizationPassesEnum {
454 RPE_BasicBlockReordering,
455 RPE_ConstantBlinding,
456 RPE_FunctionReordering,
457 RPE_GlobalVariableReordering,
458 RPE_NopInsertion,
459 RPE_PooledConstantReordering,
460 RPE_RegAllocRandomization,
461 RPE_num
462};
463
John Porto27fddcc2016-02-02 15:06:09 -0800464using RelocOffsetArray = llvm::SmallVector<class RelocOffset *, 4>;
465
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700466} // end of namespace Ice
467
468#endif // SUBZERO_SRC_ICEDEFS_H