Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 1 | //===- 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 Schimpf | 8df26f3 | 2014-09-19 09:33:26 -0700 | [diff] [blame] | 17 | #include "IceInst.h" |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 18 | #include "IceIntrinsics.h" |
| 19 | #include "IceLiveness.h" |
| 20 | #include "IceOperand.h" |
| 21 | |
| 22 | #include <utility> |
| 23 | |
| 24 | namespace Ice { |
| 25 | |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 26 | static_assert(sizeof(Intrinsics::IntrinsicInfo) == 4, |
| 27 | "Unexpected sizeof(IntrinsicInfo)"); |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 28 | |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 29 | namespace { |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 30 | |
| 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 Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 35 | const struct IceIntrinsicsEntry_ { |
| 36 | Intrinsics::FullIntrinsicInfo Info; |
| 37 | const char *IntrinsicName; |
| 38 | } IceIntrinsicsTable[] = { |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 39 | |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 40 | #define AtomicCmpxchgInit(Overload, NameSuffix) \ |
| 41 | { \ |
| 42 | { \ |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 43 | INTRIN(AtomicCmpxchg, SideEffects_T, ReturnsTwice_F), \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 44 | { Overload, IceType_i32, Overload, Overload, IceType_i32, IceType_i32 }, \ |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 45 | 6 }, \ |
| 46 | "nacl.atomic.cmpxchg." NameSuffix \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 47 | } |
| 48 | AtomicCmpxchgInit(IceType_i8, "i8"), |
| 49 | AtomicCmpxchgInit(IceType_i16, "i16"), |
| 50 | AtomicCmpxchgInit(IceType_i32, "i32"), |
| 51 | AtomicCmpxchgInit(IceType_i64, "i64"), |
| 52 | #undef AtomicCmpxchgInit |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 53 | |
| 54 | { { INTRIN(AtomicFence, SideEffects_T, ReturnsTwice_F), |
| 55 | { IceType_void, IceType_i32 }, 2 }, |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 56 | "nacl.atomic.fence" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 57 | { { INTRIN(AtomicFenceAll, SideEffects_T, ReturnsTwice_F), |
| 58 | { IceType_void }, 1 }, |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 59 | "nacl.atomic.fence.all" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 60 | { { INTRIN(AtomicIsLockFree, SideEffects_F, ReturnsTwice_F), |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 61 | { IceType_i1, IceType_i32, IceType_i32 }, 3 }, |
| 62 | "nacl.atomic.is.lock.free" }, |
| 63 | |
| 64 | #define AtomicLoadInit(Overload, NameSuffix) \ |
| 65 | { \ |
| 66 | { \ |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 67 | INTRIN(AtomicLoad, SideEffects_T, ReturnsTwice_F), \ |
| 68 | { Overload, IceType_i32, IceType_i32 }, 3 }, \ |
| 69 | "nacl.atomic.load." NameSuffix \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 70 | } |
| 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 Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 80 | INTRIN(AtomicRMW, SideEffects_T, ReturnsTwice_F) \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 81 | , { 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 Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 94 | INTRIN(AtomicStore, SideEffects_T, ReturnsTwice_F) \ |
Jan Voung | 5cd240d | 2014-06-25 10:36:46 -0700 | [diff] [blame] | 95 | , { IceType_void, Overload, IceType_i32, IceType_i32 }, 4 \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 96 | } \ |
| 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 Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 108 | INTRIN(Bswap, SideEffects_F, ReturnsTwice_F) \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 109 | , { 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 Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 121 | INTRIN(Ctlz, SideEffects_F, ReturnsTwice_F) \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 122 | , { 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 Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 133 | INTRIN(Ctpop, SideEffects_F, ReturnsTwice_F) \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 134 | , { 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 Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 145 | INTRIN(Cttz, SideEffects_F, ReturnsTwice_F) \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 146 | , { Overload, Overload, IceType_i1 }, 3 \ |
| 147 | } \ |
| 148 | , "cttz." NameSuffix \ |
| 149 | } |
| 150 | CttzInit(IceType_i32, "i32"), |
| 151 | CttzInit(IceType_i64, "i64"), |
| 152 | #undef CttzInit |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 153 | |
| 154 | { { INTRIN(Longjmp, SideEffects_T, ReturnsTwice_F), |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 155 | { IceType_void, IceType_i32, IceType_i32 }, 3 }, |
| 156 | "nacl.longjmp" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 157 | { { INTRIN(Memcpy, SideEffects_T, ReturnsTwice_F), |
| 158 | { IceType_void, IceType_i32, IceType_i32, IceType_i32, IceType_i32, |
| 159 | IceType_i1}, |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 160 | 6 }, |
| 161 | "memcpy.p0i8.p0i8.i32" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 162 | { { INTRIN(Memmove, SideEffects_T, ReturnsTwice_F), |
| 163 | { IceType_void, IceType_i32, IceType_i32, IceType_i32, IceType_i32, |
| 164 | IceType_i1 }, |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 165 | 6 }, |
| 166 | "memmove.p0i8.p0i8.i32" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 167 | { { INTRIN(Memset, SideEffects_T, ReturnsTwice_F), |
| 168 | { IceType_void, IceType_i32, IceType_i8, IceType_i32, IceType_i32, |
| 169 | IceType_i1 }, |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 170 | 6 }, |
| 171 | "memset.p0i8.i32" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 172 | { { INTRIN(NaClReadTP, SideEffects_F, ReturnsTwice_F), |
| 173 | { IceType_i32 }, 1 }, |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 174 | "nacl.read.tp" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 175 | { { INTRIN(Setjmp, SideEffects_T, ReturnsTwice_T), |
| 176 | { IceType_i32, IceType_i32 }, 2 }, |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 177 | "nacl.setjmp" }, |
| 178 | |
| 179 | #define SqrtInit(Overload, NameSuffix) \ |
| 180 | { \ |
| 181 | { \ |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 182 | INTRIN(Sqrt, SideEffects_F, ReturnsTwice_F), \ |
| 183 | { Overload, Overload }, 2 }, \ |
| 184 | "sqrt." NameSuffix \ |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 185 | } |
| 186 | SqrtInit(IceType_f32, "f32"), |
| 187 | SqrtInit(IceType_f64, "f64"), |
| 188 | #undef SqrtInit |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 189 | |
| 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 Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 195 | "stackrestore" }, |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 196 | { { INTRIN(Trap, SideEffects_T, ReturnsTwice_F), |
| 197 | { IceType_void }, 1 }, |
| 198 | "trap" } |
| 199 | }; |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 200 | const size_t IceIntrinsicsTableSize = llvm::array_lengthof(IceIntrinsicsTable); |
| 201 | |
Jan Voung | 44d53e1 | 2014-09-11 19:18:03 -0700 | [diff] [blame] | 202 | #undef INTRIN |
| 203 | |
Jim Stichnoth | 989a703 | 2014-08-08 10:13:44 -0700 | [diff] [blame] | 204 | } // end of anonymous namespace |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 205 | |
| 206 | Intrinsics::Intrinsics() { |
| 207 | for (size_t I = 0; I < IceIntrinsicsTableSize; ++I) { |
| 208 | const struct IceIntrinsicsEntry_ &Entry = IceIntrinsicsTable[I]; |
| 209 | assert(Entry.Info.NumTypes <= kMaxIntrinsicParameters); |
Jim Stichnoth | f44f371 | 2014-10-01 14:05:51 -0700 | [diff] [blame] | 210 | Map.insert(std::make_pair(IceString(Entry.IntrinsicName), Entry.Info)); |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 211 | } |
| 212 | } |
| 213 | |
| 214 | Intrinsics::~Intrinsics() {} |
| 215 | |
| 216 | const Intrinsics::FullIntrinsicInfo * |
| 217 | Intrinsics::find(const IceString &Name) const { |
Jim Stichnoth | f44f371 | 2014-10-01 14:05:51 -0700 | [diff] [blame] | 218 | auto it = Map.find(Name); |
| 219 | if (it == Map.end()) |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 220 | return NULL; |
| 221 | return &it->second; |
| 222 | } |
| 223 | |
Jan Voung | 5cd240d | 2014-06-25 10:36:46 -0700 | [diff] [blame] | 224 | bool 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 Schimpf | 8df26f3 | 2014-09-19 09:33:26 -0700 | [diff] [blame] | 229 | Intrinsics::ValidateCallValue |
| 230 | Intrinsics::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 | |
| 252 | Type Intrinsics::FullIntrinsicInfo::getArgType(SizeT Index) const { |
| 253 | assert(NumTypes > 1); |
| 254 | assert(Index + 1 < NumTypes); |
| 255 | return Signature[Index + 1]; |
| 256 | } |
| 257 | |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 258 | } // end of namespace Ice |