1 //===- subzero/src/IceIntrinsics.h - List of Ice Intrinsics -----*- C++ -*-===// 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 /// \file 11 /// \brief Declares the kinds of intrinsics supported by PNaCl. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef SUBZERO_SRC_ICEINTRINSICS_H 16 #define SUBZERO_SRC_ICEINTRINSICS_H 17 18 #include "IceDefs.h" 19 #include "IceStringPool.h" 20 #include "IceTypes.h" 21 22 namespace Ice { 23 24 class InstCall; 25 26 static constexpr size_t kMaxIntrinsicParameters = 6; 27 28 class Intrinsics { 29 Intrinsics(const Intrinsics &) = delete; 30 Intrinsics &operator=(const Intrinsics &) = delete; 31 32 public: 33 explicit Intrinsics(GlobalContext *Ctx); 34 ~Intrinsics() = default; 35 36 /// Some intrinsics allow overloading by type. This enum collapses all 37 /// overloads into a single ID, but the type can still be recovered by the 38 /// type of the intrinsic function call's return value and parameters. 39 enum IntrinsicID { 40 UnknownIntrinsic = 0, 41 // Arbitrary (alphabetical) order. 42 AtomicCmpxchg, 43 AtomicFence, 44 AtomicFenceAll, 45 AtomicIsLockFree, 46 AtomicLoad, 47 AtomicRMW, 48 AtomicStore, 49 Bswap, 50 Ctlz, 51 Ctpop, 52 Cttz, 53 Fabs, 54 Longjmp, 55 Memcpy, 56 Memmove, 57 Memset, 58 NaClReadTP, 59 Setjmp, 60 Sqrt, 61 Stacksave, 62 Stackrestore, 63 Trap, 64 // The intrinsics below are not part of the PNaCl specification. 65 AddSaturateSigned, 66 AddSaturateUnsigned, 67 LoadSubVector, 68 MultiplyAddPairs, 69 MultiplyHighSigned, 70 MultiplyHighUnsigned, 71 Nearbyint, 72 Round, 73 SignMask, 74 StoreSubVector, 75 SubtractSaturateSigned, 76 SubtractSaturateUnsigned, 77 VectorPackSigned, 78 VectorPackUnsigned 79 }; 80 81 /// Operations that can be represented by the AtomicRMW intrinsic. 82 /// 83 /// Do not reorder these values: their order offers forward compatibility of 84 /// bitcode targeted to PNaCl. 85 enum AtomicRMWOperation { 86 AtomicInvalid = 0, // Invalid, keep first. 87 AtomicAdd, 88 AtomicSub, 89 AtomicOr, 90 AtomicAnd, 91 AtomicXor, 92 AtomicExchange, 93 AtomicNum // Invalid, keep last. 94 }; 95 96 /// Memory orderings supported by PNaCl IR. 97 /// 98 /// Do not reorder these values: their order offers forward compatibility of 99 /// bitcode targeted to PNaCl. 100 enum MemoryOrder { 101 MemoryOrderInvalid = 0, // Invalid, keep first. 102 MemoryOrderRelaxed, 103 MemoryOrderConsume, 104 MemoryOrderAcquire, 105 MemoryOrderRelease, 106 MemoryOrderAcquireRelease, 107 MemoryOrderSequentiallyConsistent, 108 MemoryOrderNum // Invalid, keep last. 109 }; 110 111 /// Verify memory ordering rules for atomic intrinsics. For AtomicCmpxchg, 112 /// Order is the "success" ordering and OrderOther is the "failure" ordering. 113 /// Returns true if valid, false if invalid. 114 // TODO(stichnot,kschimpf): Perform memory order validation in the bitcode 115 // reader/parser, allowing LLVM and Subzero to share. See 116 // https://code.google.com/p/nativeclient/issues/detail?id=4126 . 117 static bool isMemoryOrderValid(IntrinsicID ID, uint64_t Order, 118 uint64_t OrderOther = MemoryOrderInvalid); 119 120 enum SideEffects { SideEffects_F = 0, SideEffects_T = 1 }; 121 122 enum ReturnsTwice { ReturnsTwice_F = 0, ReturnsTwice_T = 1 }; 123 124 enum MemoryWrite { MemoryWrite_F = 0, MemoryWrite_T = 1 }; 125 126 /// Basic attributes related to each intrinsic, that are relevant to code 127 /// generation. Perhaps the attributes representation can be shared with 128 /// general function calls, but PNaCl currently strips all attributes from 129 /// functions. 130 struct IntrinsicInfo { 131 enum IntrinsicID ID : 29; 132 enum SideEffects HasSideEffects : 1; 133 enum ReturnsTwice ReturnsTwice : 1; 134 enum MemoryWrite IsMemoryWrite : 1; 135 }; 136 static_assert(sizeof(IntrinsicInfo) == 4, "IntrinsicInfo should be 32 bits"); 137 138 /// The types of validation values for FullIntrinsicInfo.validateCall. 139 enum ValidateCallValue { 140 IsValidCall, /// Valid use of instrinsic call. 141 BadReturnType, /// Return type invalid for intrinsic. 142 WrongNumOfArgs, /// Wrong number of arguments for intrinsic. 143 WrongCallArgType, /// Argument of wrong type. 144 }; 145 146 /// The complete set of information about an intrinsic. 147 struct FullIntrinsicInfo { 148 struct IntrinsicInfo Info; /// Information that CodeGen would care about. 149 150 // Sanity check during parsing. 151 Type Signature[kMaxIntrinsicParameters]; 152 uint8_t NumTypes; 153 154 /// Validates that type signature of call matches intrinsic. If 155 /// WrongArgumentType is returned, ArgIndex is set to corresponding argument 156 /// index. 157 ValidateCallValue validateCall(const Ice::InstCall *Call, 158 SizeT &ArgIndex) const; 159 160 /// Returns the return type of the intrinsic. getReturnTypeFullIntrinsicInfo161 Type getReturnType() const { 162 assert(NumTypes > 0); 163 return Signature[0]; 164 } 165 166 /// Returns number of arguments expected. getNumArgsFullIntrinsicInfo167 SizeT getNumArgs() const { 168 assert(NumTypes > 0); 169 return NumTypes - 1; 170 } 171 172 /// Returns type of Index-th argument. 173 Type getArgType(SizeT Index) const; 174 }; 175 176 /// Find the information about a given intrinsic, based on function name. If 177 /// the function name does not have the common "llvm." prefix, nullptr is 178 /// returned and Error is set to false. Otherwise, tries to find a reference 179 /// to a FullIntrinsicInfo entry (valid for the lifetime of the map). If 180 /// found, sets Error to false and returns the reference. If not found, sets 181 /// Error to true and returns nullptr (indicating an unknown "llvm.foo" 182 /// intrinsic). 183 const FullIntrinsicInfo *find(GlobalString Name, bool &Error) const; 184 185 private: 186 // TODO(jvoung): May want to switch to something like LLVM's StringMap. 187 using IntrinsicMap = std::unordered_map<GlobalString, FullIntrinsicInfo>; 188 IntrinsicMap Map; 189 }; 190 191 } // end of namespace Ice 192 193 #endif // SUBZERO_SRC_ICEINTRINSICS_H 194