blob: ceb6fd090d41b561ae6b1ae432b8a6d36609e28a [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///
14/// Every Subzero source file is expected to include IceDefs.h.
Andrew Scull9612d322015-07-06 14:53:25 -070015///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070016//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEDEFS_H
19#define SUBZERO_SRC_ICEDEFS_H
20
John Porto67f8de92015-06-25 10:14:17 -070021#include "IceBuildDefs.h" // TODO(stichnot): move into individual files
22#include "IceTLS.h"
23
Jan Voungb17f61d2014-08-28 16:00:53 -070024#include "llvm/ADT/ArrayRef.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070025#include "llvm/ADT/BitVector.h"
Jim Stichnoth607e9f02014-11-06 13:32:05 -080026#include "llvm/ADT/ilist.h"
27#include "llvm/ADT/ilist_node.h"
Jim Stichnoth7e571362015-01-09 11:43:26 -080028#include "llvm/ADT/iterator_range.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070029#include "llvm/ADT/SmallBitVector.h"
Jim Stichnoth586d4c22014-12-05 16:43:08 -080030#include "llvm/ADT/SmallVector.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070031#include "llvm/ADT/STLExtras.h"
Jim Stichnoth31c95592014-12-19 12:51:35 -080032#include "llvm/Support/Allocator.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070033#include "llvm/Support/Casting.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080034#include "llvm/Support/ELF.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070035#include "llvm/Support/raw_ostream.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070036
John Porto67f8de92015-06-25 10:14:17 -070037#include <cassert>
38#include <cstdint>
39#include <cstdio> // snprintf
40#include <functional> // std::less
41#include <limits>
42#include <list>
43#include <map>
44#include <memory>
45#include <mutex>
46#include <string>
47#include <system_error>
Karl Schimpfac7d7342015-08-06 12:55:23 -070048#include <unordered_map>
John Porto67f8de92015-06-25 10:14:17 -070049#include <vector>
Jim Stichnoth7d538252015-01-23 10:22:56 -080050
Jim Stichnothf7c9a142014-04-29 10:52:43 -070051namespace Ice {
52
Jan Voungec270732015-01-12 17:00:22 -080053class Assembler;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070054class Cfg;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070055class CfgNode;
56class Constant;
Jan Voungec270732015-01-12 17:00:22 -080057class ELFObjectWriter;
58class ELFStreamer;
Karl Schimpf9d98d792014-10-13 15:01:08 -070059class FunctionDeclaration;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070060class GlobalContext;
Karl Schimpf9d98d792014-10-13 15:01:08 -070061class GlobalDeclaration;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070062class Inst;
Jim Stichnoth336f6c42014-10-30 15:01:31 -070063class InstAssign;
Andrew Scull86df4e92015-07-30 13:54:44 -070064class InstJumpTable;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065class InstPhi;
Andrew Scull86df4e92015-07-30 13:54:44 -070066class InstSwitch;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067class InstTarget;
Jim Stichnothd97c7df2014-06-04 11:57:08 -070068class LiveRange;
69class Liveness;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070070class Operand;
Jan Voung72984d82015-01-29 14:42:38 -080071class TargetDataLowering;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070072class TargetLowering;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070073class Variable;
Karl Schimpf9d98d792014-10-13 15:01:08 -070074class VariableDeclaration;
Jim Stichnoth144cdce2014-09-22 16:02:59 -070075class VariablesMetadata;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070076
Jan Voung1d62cf02015-01-09 14:57:32 -080077template <size_t SlabSize = 1024 * 1024>
78using ArenaAllocator =
79 llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, SlabSize>;
Jim Stichnoth31c95592014-12-19 12:51:35 -080080
Jan Voung1d62cf02015-01-09 14:57:32 -080081ArenaAllocator<> *getCurrentCfgAllocator();
Jim Stichnoth31c95592014-12-19 12:51:35 -080082
83template <typename T> struct CfgLocalAllocator {
84 using value_type = T;
Jim Stichnoth91d1b802015-10-01 13:24:34 -070085 using pointer = T *;
86 using const_pointer = const T *;
87 using reference = T &;
88 using const_reference = const T &;
89 using size_type = std::size_t;
Jim Stichnoth31c95592014-12-19 12:51:35 -080090 CfgLocalAllocator() = default;
91 template <class U> CfgLocalAllocator(const CfgLocalAllocator<U> &) {}
Jim Stichnoth91d1b802015-10-01 13:24:34 -070092 pointer allocate(size_type Num) {
Jim Stichnoth31c95592014-12-19 12:51:35 -080093 return getCurrentCfgAllocator()->Allocate<T>(Num);
94 }
Jim Stichnoth91d1b802015-10-01 13:24:34 -070095 void deallocate(pointer, size_type) {}
96 template <class U> struct rebind { typedef CfgLocalAllocator<U> other; };
97 void construct(pointer P, const T &Val) {
98 new (static_cast<void *>(P)) T(Val);
99 }
100 void destroy(pointer P) { P->~T(); }
Jim Stichnoth31c95592014-12-19 12:51:35 -0800101};
102template <typename T, typename U>
103inline bool operator==(const CfgLocalAllocator<T> &,
104 const CfgLocalAllocator<U> &) {
105 return true;
106}
107template <typename T, typename U>
108inline bool operator!=(const CfgLocalAllocator<T> &,
109 const CfgLocalAllocator<U> &) {
110 return false;
111}
112
John Porto1bec8bc2015-06-22 10:51:13 -0700113// makeUnique should be used when memory is expected to be allocated from the
Andrew Scull57e12682015-09-16 11:30:19 -0700114// heap (as opposed to allocated from some Allocator.) It is intended to be
115// used instead of new.
John Porto1bec8bc2015-06-22 10:51:13 -0700116//
117// The expected usage is as follows
118//
119// class MyClass {
120// public:
121// static std::unique_ptr<MyClass> create(<ctor_args>) {
122// return makeUnique<MyClass>(<ctor_args>);
123// }
124//
125// private:
126// ENABLE_MAKE_UNIQUE;
127//
128// MyClass(<ctor_args>) ...
129// }
130//
131// ENABLE_MAKE_UNIQUE is a trick that is necessary if MyClass' ctor is private.
132// Private ctors are highly encouraged when you're writing a class that you'd
133// like to have allocated with makeUnique as it would prevent users from
134// declaring stack allocated variables.
135namespace Internal {
136struct MakeUniqueEnabler {
137 template <class T, class... Args>
138 static std::unique_ptr<T> create(Args &&... TheArgs) {
139 std::unique_ptr<T> Unique(new T(std::forward<Args>(TheArgs)...));
140 return Unique;
141 }
142};
143} // end of namespace Internal
144
145template <class T, class... Args>
146static std::unique_ptr<T> makeUnique(Args &&... TheArgs) {
147 return ::Ice::Internal::MakeUniqueEnabler::create<T>(
148 std::forward<Args>(TheArgs)...);
149}
150
151#define ENABLE_MAKE_UNIQUE friend struct ::Ice::Internal::MakeUniqueEnabler
152
Andrew Scull8072bae2015-09-14 16:01:26 -0700153using IceString = std::string;
154using InstList = llvm::ilist<Inst>;
Andrew Scull57e12682015-09-16 11:30:19 -0700155// Ideally PhiList would be llvm::ilist<InstPhi>, and similar for AssignList,
156// but this runs into issues with SFINAE.
Andrew Scull8072bae2015-09-14 16:01:26 -0700157using PhiList = InstList;
158using AssignList = InstList;
Karl Schimpf209318a2015-08-20 13:24:02 -0700159
Andrew Scull00741a02015-09-16 19:04:09 -0700160// Standard library containers with CfgLocalAllocator.
161template <typename T> using CfgVector = std::vector<T, CfgLocalAllocator<T>>;
162template <typename T> using CfgList = std::list<T, CfgLocalAllocator<T>>;
163
Karl Schimpf209318a2015-08-20 13:24:02 -0700164// Containers that are arena-allocated from the Cfg's allocator.
Andrew Scull00741a02015-09-16 19:04:09 -0700165using OperandList = CfgVector<Operand *>;
166using VarList = CfgVector<Variable *>;
167using NodeList = CfgVector<CfgNode *>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700168
Karl Schimpf209318a2015-08-20 13:24:02 -0700169// Contains that use the default (global) allocator.
Andrew Scull8072bae2015-09-14 16:01:26 -0700170using ConstantList = std::vector<Constant *>;
171using FunctionDeclarationList = std::vector<FunctionDeclaration *>;
172using VariableDeclarationList = std::vector<VariableDeclaration *>;
Jan Voung72984d82015-01-29 14:42:38 -0800173
Andrew Scull57e12682015-09-16 11:30:19 -0700174/// SizeT is for holding small-ish limits like number of source operands in an
175/// instruction. It is used instead of size_t (which may be 64-bits wide) when
176/// we want to save space.
Andrew Scull8072bae2015-09-14 16:01:26 -0700177using SizeT = uint32_t;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700178
Andrew Scull57e12682015-09-16 11:30:19 -0700179/// InstNumberT is for holding an instruction number. Instruction numbers are
180/// used for representing Variable live ranges.
Andrew Scull8072bae2015-09-14 16:01:26 -0700181using InstNumberT = int32_t;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700182
Andrew Scull57e12682015-09-16 11:30:19 -0700183/// A LiveBeginEndMapEntry maps a Variable::Number value to an Inst::Number
184/// value, giving the instruction number that begins or ends a variable's live
185/// range.
Andrew Scull8072bae2015-09-14 16:01:26 -0700186using LiveBeginEndMapEntry = std::pair<SizeT, InstNumberT>;
Andrew Scull00741a02015-09-16 19:04:09 -0700187using LiveBeginEndMap = CfgVector<LiveBeginEndMapEntry>;
Andrew Scull8072bae2015-09-14 16:01:26 -0700188using LivenessBV = llvm::BitVector;
Jim Stichnoth47752552014-10-13 17:15:08 -0700189
Andrew Scull8072bae2015-09-14 16:01:26 -0700190using TimerStackIdT = uint32_t;
191using TimerIdT = uint32_t;
Jim Stichnothc4554d72014-09-30 16:49:38 -0700192
Andrew Scull57e12682015-09-16 11:30:19 -0700193/// Use alignas(MaxCacheLineSize) to isolate variables/fields that might be
194/// contended while multithreading. Assumes the maximum cache line size is 64.
Jim Stichnothdd842db2015-01-27 12:53:53 -0800195enum { MaxCacheLineSize = 64 };
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800196// Use ICE_CACHELINE_BOUNDARY to force the next field in a declaration
197// list to be aligned to the next cache line.
JF Bastien867684e2015-01-28 15:07:38 -0800198// Note: zero is added to work around the following GCC 4.8 bug (fixed in 4.9):
199// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55382
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800200#define ICE_CACHELINE_BOUNDARY \
JF Bastien867684e2015-01-28 15:07:38 -0800201 __attribute__((aligned(MaxCacheLineSize + 0))) int : 0
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800202
Andrew Scull9612d322015-07-06 14:53:25 -0700203/// PNaCl is ILP32, so theoretically we should only need 32-bit offsets.
Andrew Scull8072bae2015-09-14 16:01:26 -0700204using RelocOffsetT = int32_t;
Jan Voungc0d965f2014-11-04 16:55:01 -0800205enum { RelocAddrSize = 4 };
Jan Voungfe14fb82014-10-13 15:56:32 -0700206
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700207enum LivenessMode {
Andrew Scull57e12682015-09-16 11:30:19 -0700208 /// Basic version of live-range-end calculation. Marks the last uses of
209 /// variables based on dataflow analysis. Records the set of live-in and
210 /// live-out variables for each block. Identifies and deletes dead
211 /// instructions (primarily stores).
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700212 Liveness_Basic,
213
Andrew Scull57e12682015-09-16 11:30:19 -0700214 /// In addition to Liveness_Basic, also calculate the complete live range for
215 /// each variable in a form suitable for interference calculation and register
216 /// allocation.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700217 Liveness_Intervals
218};
219
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800220enum RegAllocKind {
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700221 RAK_Unknown,
Jim Stichnoth4001c932015-10-09 14:33:26 -0700222 RAK_Global, /// full, global register allocation
223 RAK_SecondChance, /// second-chance bin-packing after full regalloc attempt
224 RAK_Phi, /// infinite-weight Variables with active spilling/filling
225 RAK_InfOnly /// allocation only for infinite-weight Variables
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800226};
227
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700228enum VerboseItem {
229 IceV_None = 0,
230 IceV_Instructions = 1 << 0,
231 IceV_Deleted = 1 << 1,
232 IceV_InstNumbers = 1 << 2,
233 IceV_Preds = 1 << 3,
234 IceV_Succs = 1 << 4,
235 IceV_Liveness = 1 << 5,
Jim Stichnoth769be682015-01-15 09:05:08 -0800236 IceV_RegOrigins = 1 << 6,
237 IceV_LinearScan = 1 << 7,
238 IceV_Frame = 1 << 8,
239 IceV_AddrOpt = 1 << 9,
240 IceV_Random = 1 << 10,
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700241 IceV_Folding = 1 << 11,
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700242 IceV_RMW = 1 << 12,
Andrew Scullaa6c1092015-09-03 17:50:30 -0700243 IceV_Loop = 1 << 13,
Jim Stichnotha5229652015-11-12 10:25:21 -0800244 IceV_Status = 1 << 14,
Jim Stichnothad403532014-09-25 12:44:17 -0700245 IceV_All = ~IceV_None,
Jim Stichnothc4554d72014-09-30 16:49:38 -0700246 IceV_Most = IceV_All & ~IceV_LinearScan
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700247};
Andrew Scull8072bae2015-09-14 16:01:26 -0700248using VerboseMask = uint32_t;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700249
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800250enum FileType {
Andrew Scull9612d322015-07-06 14:53:25 -0700251 FT_Elf, /// ELF .o file
252 FT_Asm, /// Assembly .s file
253 FT_Iasm /// "Integrated assembler" .byte-style .s file
Jim Stichnothd442e7e2015-02-12 14:01:48 -0800254};
255
Andrew Scull8072bae2015-09-14 16:01:26 -0700256using Ostream = llvm::raw_ostream;
257using Fdstream = llvm::raw_fd_ostream;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700258
Andrew Scull8072bae2015-09-14 16:01:26 -0700259using GlobalLockType = std::mutex;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800260
Jim Stichnothdd842db2015-01-27 12:53:53 -0800261enum ErrorCodes { EC_None = 0, EC_Args, EC_Bitcode, EC_Translation };
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800262
Andrew Scull57e12682015-09-16 11:30:19 -0700263/// Wrapper around std::error_code for allowing multiple errors to be folded
264/// into one. The current implementation keeps track of the first error, which
265/// is likely to be the most useful one, and this could be extended to e.g.
266/// collect a vector of errors.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800267class ErrorCode : public std::error_code {
268 ErrorCode(const ErrorCode &) = delete;
269 ErrorCode &operator=(const ErrorCode &) = delete;
270
271public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700272 ErrorCode() = default;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800273 void assign(ErrorCodes Code) {
274 if (!HasError) {
275 HasError = true;
276 std::error_code::assign(Code, std::generic_category());
277 }
278 }
279 void assign(int Code) { assign(static_cast<ErrorCodes>(Code)); }
280
281private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700282 bool HasError = false;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800283};
284
Andrew Scull9612d322015-07-06 14:53:25 -0700285/// Reverse range adaptors written in terms of llvm::make_range().
Jim Stichnoth7e571362015-01-09 11:43:26 -0800286template <typename T>
287llvm::iterator_range<typename T::const_reverse_iterator>
288reverse_range(const T &Container) {
289 return llvm::make_range(Container.rbegin(), Container.rend());
290}
291template <typename T>
292llvm::iterator_range<typename T::reverse_iterator> reverse_range(T &Container) {
293 return llvm::make_range(Container.rbegin(), Container.rend());
294}
295
Andrew Scull9612d322015-07-06 14:53:25 -0700296/// Options for pooling and randomization of immediates.
Qining Lu253dc8a2015-06-22 10:10:23 -0700297enum RandomizeAndPoolImmediatesEnum { RPI_None, RPI_Randomize, RPI_Pool };
298
Qining Luaee5fa82015-08-20 14:59:03 -0700299/// Salts for Random number generator for different randomization passes.
300enum RandomizationPassesEnum {
301 RPE_BasicBlockReordering,
302 RPE_ConstantBlinding,
303 RPE_FunctionReordering,
304 RPE_GlobalVariableReordering,
305 RPE_NopInsertion,
306 RPE_PooledConstantReordering,
307 RPE_RegAllocRandomization,
308 RPE_num
309};
310
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700311} // end of namespace Ice
312
313#endif // SUBZERO_SRC_ICEDEFS_H