blob: 2c97809a11bf957dfbe508378bede46681697bd0 [file] [log] [blame]
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001//===- subzero/src/IceIntrinsics.cpp - Functions related to intrinsics ----===//
2//
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//===----------------------------------------------------------------------===//
9//
10// This file implements the Intrinsics utilities for matching and
11// then dispatching by name.
12//
13//===----------------------------------------------------------------------===//
14
15#include "IceCfg.h"
16#include "IceCfgNode.h"
Karl Schimpf8df26f32014-09-19 09:33:26 -070017#include "IceInst.h"
Jan Voung3bd9f1a2014-06-18 10:50:57 -070018#include "IceIntrinsics.h"
19#include "IceLiveness.h"
20#include "IceOperand.h"
21
22#include <utility>
23
24namespace Ice {
25
Jim Stichnothfac55172014-10-01 13:06:21 -070026static_assert(sizeof(Intrinsics::IntrinsicInfo) == 4,
27 "Unexpected sizeof(IntrinsicInfo)");
Jan Voung3bd9f1a2014-06-18 10:50:57 -070028
Jim Stichnothfac55172014-10-01 13:06:21 -070029namespace {
Jan Voung44d53e12014-09-11 19:18:03 -070030
31#define INTRIN(ID, SE, RT) { Intrinsics::ID, Intrinsics::SE, Intrinsics::RT }
32
33// Build list of intrinsics with their attributes and expected prototypes.
34// List is sorted alphabetically.
Jan Voung3bd9f1a2014-06-18 10:50:57 -070035const struct IceIntrinsicsEntry_ {
36 Intrinsics::FullIntrinsicInfo Info;
37 const char *IntrinsicName;
38} IceIntrinsicsTable[] = {
Jan Voung44d53e12014-09-11 19:18:03 -070039
Jan Voung3bd9f1a2014-06-18 10:50:57 -070040#define AtomicCmpxchgInit(Overload, NameSuffix) \
41 { \
42 { \
Jan Voung44d53e12014-09-11 19:18:03 -070043 INTRIN(AtomicCmpxchg, SideEffects_T, ReturnsTwice_F), \
Jan Voung3bd9f1a2014-06-18 10:50:57 -070044 { Overload, IceType_i32, Overload, Overload, IceType_i32, IceType_i32 }, \
Jan Voung44d53e12014-09-11 19:18:03 -070045 6 }, \
46 "nacl.atomic.cmpxchg." NameSuffix \
Jan Voung3bd9f1a2014-06-18 10:50:57 -070047 }
48 AtomicCmpxchgInit(IceType_i8, "i8"),
49 AtomicCmpxchgInit(IceType_i16, "i16"),
50 AtomicCmpxchgInit(IceType_i32, "i32"),
51 AtomicCmpxchgInit(IceType_i64, "i64"),
52#undef AtomicCmpxchgInit
Jan Voung44d53e12014-09-11 19:18:03 -070053
54 { { INTRIN(AtomicFence, SideEffects_T, ReturnsTwice_F),
55 { IceType_void, IceType_i32 }, 2 },
Jan Voung3bd9f1a2014-06-18 10:50:57 -070056 "nacl.atomic.fence" },
Jan Voung44d53e12014-09-11 19:18:03 -070057 { { INTRIN(AtomicFenceAll, SideEffects_T, ReturnsTwice_F),
58 { IceType_void }, 1 },
Jan Voung3bd9f1a2014-06-18 10:50:57 -070059 "nacl.atomic.fence.all" },
Jan Voung44d53e12014-09-11 19:18:03 -070060 { { INTRIN(AtomicIsLockFree, SideEffects_F, ReturnsTwice_F),
Jan Voung3bd9f1a2014-06-18 10:50:57 -070061 { IceType_i1, IceType_i32, IceType_i32 }, 3 },
62 "nacl.atomic.is.lock.free" },
63
64#define AtomicLoadInit(Overload, NameSuffix) \
65 { \
66 { \
Jan Voung44d53e12014-09-11 19:18:03 -070067 INTRIN(AtomicLoad, SideEffects_T, ReturnsTwice_F), \
68 { Overload, IceType_i32, IceType_i32 }, 3 }, \
69 "nacl.atomic.load." NameSuffix \
Jan Voung3bd9f1a2014-06-18 10:50:57 -070070 }
71 AtomicLoadInit(IceType_i8, "i8"),
72 AtomicLoadInit(IceType_i16, "i16"),
73 AtomicLoadInit(IceType_i32, "i32"),
74 AtomicLoadInit(IceType_i64, "i64"),
75#undef AtomicLoadInit
76
77#define AtomicRMWInit(Overload, NameSuffix) \
78 { \
79 { \
Jan Voung44d53e12014-09-11 19:18:03 -070080 INTRIN(AtomicRMW, SideEffects_T, ReturnsTwice_F) \
Jan Voung3bd9f1a2014-06-18 10:50:57 -070081 , { Overload, IceType_i32, IceType_i32, Overload, IceType_i32 }, 5 \
82 } \
83 , "nacl.atomic.rmw." NameSuffix \
84 }
85 AtomicRMWInit(IceType_i8, "i8"),
86 AtomicRMWInit(IceType_i16, "i16"),
87 AtomicRMWInit(IceType_i32, "i32"),
88 AtomicRMWInit(IceType_i64, "i64"),
89#undef AtomicRMWInit
90
91#define AtomicStoreInit(Overload, NameSuffix) \
92 { \
93 { \
Jan Voung44d53e12014-09-11 19:18:03 -070094 INTRIN(AtomicStore, SideEffects_T, ReturnsTwice_F) \
Jan Voung5cd240d2014-06-25 10:36:46 -070095 , { IceType_void, Overload, IceType_i32, IceType_i32 }, 4 \
Jan Voung3bd9f1a2014-06-18 10:50:57 -070096 } \
97 , "nacl.atomic.store." NameSuffix \
98 }
99 AtomicStoreInit(IceType_i8, "i8"),
100 AtomicStoreInit(IceType_i16, "i16"),
101 AtomicStoreInit(IceType_i32, "i32"),
102 AtomicStoreInit(IceType_i64, "i64"),
103#undef AtomicStoreInit
104
105#define BswapInit(Overload, NameSuffix) \
106 { \
107 { \
Jan Voung44d53e12014-09-11 19:18:03 -0700108 INTRIN(Bswap, SideEffects_F, ReturnsTwice_F) \
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700109 , { Overload, Overload }, 2 \
110 } \
111 , "bswap." NameSuffix \
112 }
113 BswapInit(IceType_i16, "i16"),
114 BswapInit(IceType_i32, "i32"),
115 BswapInit(IceType_i64, "i64"),
116#undef BswapInit
117
118#define CtlzInit(Overload, NameSuffix) \
119 { \
120 { \
Jan Voung44d53e12014-09-11 19:18:03 -0700121 INTRIN(Ctlz, SideEffects_F, ReturnsTwice_F) \
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700122 , { Overload, Overload, IceType_i1 }, 3 \
123 } \
124 , "ctlz." NameSuffix \
125 }
126 CtlzInit(IceType_i32, "i32"),
127 CtlzInit(IceType_i64, "i64"),
128#undef CtlzInit
129
130#define CtpopInit(Overload, NameSuffix) \
131 { \
132 { \
Jan Voung44d53e12014-09-11 19:18:03 -0700133 INTRIN(Ctpop, SideEffects_F, ReturnsTwice_F) \
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700134 , { Overload, Overload }, 2 \
135 } \
136 , "ctpop." NameSuffix \
137 }
138 CtpopInit(IceType_i32, "i32"),
139 CtpopInit(IceType_i64, "i64"),
140#undef CtpopInit
141
142#define CttzInit(Overload, NameSuffix) \
143 { \
144 { \
Jan Voung44d53e12014-09-11 19:18:03 -0700145 INTRIN(Cttz, SideEffects_F, ReturnsTwice_F) \
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700146 , { Overload, Overload, IceType_i1 }, 3 \
147 } \
148 , "cttz." NameSuffix \
149 }
150 CttzInit(IceType_i32, "i32"),
151 CttzInit(IceType_i64, "i64"),
152#undef CttzInit
Jan Voung44d53e12014-09-11 19:18:03 -0700153
154 { { INTRIN(Longjmp, SideEffects_T, ReturnsTwice_F),
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700155 { IceType_void, IceType_i32, IceType_i32 }, 3 },
156 "nacl.longjmp" },
Jan Voung44d53e12014-09-11 19:18:03 -0700157 { { INTRIN(Memcpy, SideEffects_T, ReturnsTwice_F),
158 { IceType_void, IceType_i32, IceType_i32, IceType_i32, IceType_i32,
159 IceType_i1},
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700160 6 },
161 "memcpy.p0i8.p0i8.i32" },
Jan Voung44d53e12014-09-11 19:18:03 -0700162 { { INTRIN(Memmove, SideEffects_T, ReturnsTwice_F),
163 { IceType_void, IceType_i32, IceType_i32, IceType_i32, IceType_i32,
164 IceType_i1 },
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700165 6 },
166 "memmove.p0i8.p0i8.i32" },
Jan Voung44d53e12014-09-11 19:18:03 -0700167 { { INTRIN(Memset, SideEffects_T, ReturnsTwice_F),
168 { IceType_void, IceType_i32, IceType_i8, IceType_i32, IceType_i32,
169 IceType_i1 },
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700170 6 },
171 "memset.p0i8.i32" },
Jan Voung44d53e12014-09-11 19:18:03 -0700172 { { INTRIN(NaClReadTP, SideEffects_F, ReturnsTwice_F),
173 { IceType_i32 }, 1 },
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700174 "nacl.read.tp" },
Jan Voung44d53e12014-09-11 19:18:03 -0700175 { { INTRIN(Setjmp, SideEffects_T, ReturnsTwice_T),
176 { IceType_i32, IceType_i32 }, 2 },
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700177 "nacl.setjmp" },
178
179#define SqrtInit(Overload, NameSuffix) \
180 { \
181 { \
Jan Voung44d53e12014-09-11 19:18:03 -0700182 INTRIN(Sqrt, SideEffects_F, ReturnsTwice_F), \
183 { Overload, Overload }, 2 }, \
184 "sqrt." NameSuffix \
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700185 }
186 SqrtInit(IceType_f32, "f32"),
187 SqrtInit(IceType_f64, "f64"),
188#undef SqrtInit
Jan Voung44d53e12014-09-11 19:18:03 -0700189
190 { { INTRIN(Stacksave, SideEffects_T, ReturnsTwice_F),
191 { IceType_i32 }, 1 },
192 "stacksave" },
193 { { INTRIN(Stackrestore, SideEffects_T, ReturnsTwice_F),
194 { IceType_void, IceType_i32 }, 2 },
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700195 "stackrestore" },
Jan Voung44d53e12014-09-11 19:18:03 -0700196 { { INTRIN(Trap, SideEffects_T, ReturnsTwice_F),
197 { IceType_void }, 1 },
198 "trap" }
199};
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700200const size_t IceIntrinsicsTableSize = llvm::array_lengthof(IceIntrinsicsTable);
201
Jan Voung44d53e12014-09-11 19:18:03 -0700202#undef INTRIN
203
Jim Stichnoth989a7032014-08-08 10:13:44 -0700204} // end of anonymous namespace
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700205
206Intrinsics::Intrinsics() {
207 for (size_t I = 0; I < IceIntrinsicsTableSize; ++I) {
208 const struct IceIntrinsicsEntry_ &Entry = IceIntrinsicsTable[I];
209 assert(Entry.Info.NumTypes <= kMaxIntrinsicParameters);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700210 Map.insert(std::make_pair(IceString(Entry.IntrinsicName), Entry.Info));
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700211 }
212}
213
214Intrinsics::~Intrinsics() {}
215
216const Intrinsics::FullIntrinsicInfo *
217Intrinsics::find(const IceString &Name) const {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700218 auto it = Map.find(Name);
219 if (it == Map.end())
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700220 return NULL;
221 return &it->second;
222}
223
Jan Voung5cd240d2014-06-25 10:36:46 -0700224bool Intrinsics::VerifyMemoryOrder(uint64_t Order) {
225 // There is only one memory ordering for atomics allowed right now.
226 return Order == Intrinsics::MemoryOrderSequentiallyConsistent;
227}
228
Karl Schimpf8df26f32014-09-19 09:33:26 -0700229Intrinsics::ValidateCallValue
230Intrinsics::FullIntrinsicInfo::validateCall(const Ice::InstCall *Call,
231 SizeT &ArgIndex) const {
232 assert(NumTypes >= 1);
233 Variable *Result = Call->getDest();
234 if (Result == NULL) {
235 if (Signature[0] != Ice::IceType_void)
236 return Intrinsics::BadReturnType;
237 } else if (Signature[0] != Result->getType()) {
238 return Intrinsics::BadReturnType;
239 }
240 if (Call->getNumArgs() + 1 != NumTypes) {
241 return Intrinsics::WrongNumOfArgs;
242 }
243 for (size_t i = 1; i < NumTypes; ++i) {
244 if (Call->getArg(i - 1)->getType() != Signature[i]) {
245 ArgIndex = i;
246 return Intrinsics::WrongCallArgType;
247 }
248 }
249 return Intrinsics::IsValidCall;
250}
251
252Type Intrinsics::FullIntrinsicInfo::getArgType(SizeT Index) const {
253 assert(NumTypes > 1);
254 assert(Index + 1 < NumTypes);
255 return Signature[Index + 1];
256}
257
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700258} // end of namespace Ice