|  | //===- subzero/src/IceIntrinsics.h - List of Ice Intrinsics -----*- C++ -*-===// | 
|  | // | 
|  | //                        The Subzero Code Generator | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// \brief Declares the kinds of intrinsics supported by PNaCl. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef SUBZERO_SRC_ICEINTRINSICS_H | 
|  | #define SUBZERO_SRC_ICEINTRINSICS_H | 
|  |  | 
|  | #include "IceDefs.h" | 
|  | #include "IceStringPool.h" | 
|  | #include "IceTypes.h" | 
|  |  | 
|  | namespace Ice { | 
|  |  | 
|  | class InstCall; | 
|  |  | 
|  | static constexpr size_t kMaxIntrinsicParameters = 6; | 
|  |  | 
|  | class Intrinsics { | 
|  | Intrinsics(const Intrinsics &) = delete; | 
|  | Intrinsics &operator=(const Intrinsics &) = delete; | 
|  |  | 
|  | public: | 
|  | explicit Intrinsics(GlobalContext *Ctx); | 
|  | ~Intrinsics() = default; | 
|  |  | 
|  | /// Some intrinsics allow overloading by type. This enum collapses all | 
|  | /// overloads into a single ID, but the type can still be recovered by the | 
|  | /// type of the intrinsic function call's return value and parameters. | 
|  | enum IntrinsicID { | 
|  | UnknownIntrinsic = 0, | 
|  | // Arbitrary (alphabetical) order. | 
|  | AtomicCmpxchg, | 
|  | AtomicFence, | 
|  | AtomicFenceAll, | 
|  | AtomicIsLockFree, | 
|  | AtomicLoad, | 
|  | AtomicRMW, | 
|  | AtomicStore, | 
|  | Bswap, | 
|  | Ctlz, | 
|  | Ctpop, | 
|  | Cttz, | 
|  | Fabs, | 
|  | Longjmp, | 
|  | Memcpy, | 
|  | Memmove, | 
|  | Memset, | 
|  | NaClReadTP, | 
|  | Setjmp, | 
|  | Sqrt, | 
|  | Stacksave, | 
|  | Stackrestore, | 
|  | Trap, | 
|  | // The intrinsics below are not part of the PNaCl specification. | 
|  | AddSaturateSigned, | 
|  | AddSaturateUnsigned, | 
|  | LoadSubVector, | 
|  | MultiplyAddPairs, | 
|  | MultiplyHighSigned, | 
|  | MultiplyHighUnsigned, | 
|  | Nearbyint, | 
|  | Round, | 
|  | SignMask, | 
|  | StoreSubVector, | 
|  | SubtractSaturateSigned, | 
|  | SubtractSaturateUnsigned, | 
|  | VectorPackSigned, | 
|  | VectorPackUnsigned | 
|  | }; | 
|  |  | 
|  | /// Operations that can be represented by the AtomicRMW intrinsic. | 
|  | /// | 
|  | /// Do not reorder these values: their order offers forward compatibility of | 
|  | /// bitcode targeted to PNaCl. | 
|  | enum AtomicRMWOperation { | 
|  | AtomicInvalid = 0, // Invalid, keep first. | 
|  | AtomicAdd, | 
|  | AtomicSub, | 
|  | AtomicOr, | 
|  | AtomicAnd, | 
|  | AtomicXor, | 
|  | AtomicExchange, | 
|  | AtomicNum // Invalid, keep last. | 
|  | }; | 
|  |  | 
|  | /// Memory orderings supported by PNaCl IR. | 
|  | /// | 
|  | /// Do not reorder these values: their order offers forward compatibility of | 
|  | /// bitcode targeted to PNaCl. | 
|  | enum MemoryOrder { | 
|  | MemoryOrderInvalid = 0, // Invalid, keep first. | 
|  | MemoryOrderRelaxed, | 
|  | MemoryOrderConsume, | 
|  | MemoryOrderAcquire, | 
|  | MemoryOrderRelease, | 
|  | MemoryOrderAcquireRelease, | 
|  | MemoryOrderSequentiallyConsistent, | 
|  | MemoryOrderNum // Invalid, keep last. | 
|  | }; | 
|  |  | 
|  | /// Verify memory ordering rules for atomic intrinsics. For AtomicCmpxchg, | 
|  | /// Order is the "success" ordering and OrderOther is the "failure" ordering. | 
|  | /// Returns true if valid, false if invalid. | 
|  | // TODO(stichnot,kschimpf): Perform memory order validation in the bitcode | 
|  | // reader/parser, allowing LLVM and Subzero to share. See | 
|  | // https://code.google.com/p/nativeclient/issues/detail?id=4126 . | 
|  | static bool isMemoryOrderValid(IntrinsicID ID, uint64_t Order, | 
|  | uint64_t OrderOther = MemoryOrderInvalid); | 
|  |  | 
|  | enum SideEffects { SideEffects_F = 0, SideEffects_T = 1 }; | 
|  |  | 
|  | enum ReturnsTwice { ReturnsTwice_F = 0, ReturnsTwice_T = 1 }; | 
|  |  | 
|  | enum MemoryWrite { MemoryWrite_F = 0, MemoryWrite_T = 1 }; | 
|  |  | 
|  | /// Basic attributes related to each intrinsic, that are relevant to code | 
|  | /// generation. Perhaps the attributes representation can be shared with | 
|  | /// general function calls, but PNaCl currently strips all attributes from | 
|  | /// functions. | 
|  | struct IntrinsicInfo { | 
|  | enum IntrinsicID ID : 29; | 
|  | enum SideEffects HasSideEffects : 1; | 
|  | enum ReturnsTwice ReturnsTwice : 1; | 
|  | enum MemoryWrite IsMemoryWrite : 1; | 
|  | }; | 
|  | static_assert(sizeof(IntrinsicInfo) == 4, "IntrinsicInfo should be 32 bits"); | 
|  |  | 
|  | /// The types of validation values for FullIntrinsicInfo.validateCall. | 
|  | enum ValidateCallValue { | 
|  | IsValidCall,      /// Valid use of instrinsic call. | 
|  | BadReturnType,    /// Return type invalid for intrinsic. | 
|  | WrongNumOfArgs,   /// Wrong number of arguments for intrinsic. | 
|  | WrongCallArgType, /// Argument of wrong type. | 
|  | }; | 
|  |  | 
|  | /// The complete set of information about an intrinsic. | 
|  | struct FullIntrinsicInfo { | 
|  | struct IntrinsicInfo Info; /// Information that CodeGen would care about. | 
|  |  | 
|  | // Sanity check during parsing. | 
|  | Type Signature[kMaxIntrinsicParameters]; | 
|  | uint8_t NumTypes; | 
|  |  | 
|  | /// Validates that type signature of call matches intrinsic. If | 
|  | /// WrongArgumentType is returned, ArgIndex is set to corresponding argument | 
|  | /// index. | 
|  | ValidateCallValue validateCall(const Ice::InstCall *Call, | 
|  | SizeT &ArgIndex) const; | 
|  |  | 
|  | /// Returns the return type of the intrinsic. | 
|  | Type getReturnType() const { | 
|  | assert(NumTypes > 0); | 
|  | return Signature[0]; | 
|  | } | 
|  |  | 
|  | /// Returns number of arguments expected. | 
|  | SizeT getNumArgs() const { | 
|  | assert(NumTypes > 0); | 
|  | return NumTypes - 1; | 
|  | } | 
|  |  | 
|  | /// Returns type of Index-th argument. | 
|  | Type getArgType(SizeT Index) const; | 
|  | }; | 
|  |  | 
|  | /// Find the information about a given intrinsic, based on function name. If | 
|  | /// the function name does not have the common "llvm." prefix, nullptr is | 
|  | /// returned and Error is set to false. Otherwise, tries to find a reference | 
|  | /// to a FullIntrinsicInfo entry (valid for the lifetime of the map). If | 
|  | /// found, sets Error to false and returns the reference. If not found, sets | 
|  | /// Error to true and returns nullptr (indicating an unknown "llvm.foo" | 
|  | /// intrinsic). | 
|  | const FullIntrinsicInfo *find(GlobalString Name, bool &Error) const; | 
|  |  | 
|  | private: | 
|  | // TODO(jvoung): May want to switch to something like LLVM's StringMap. | 
|  | using IntrinsicMap = std::unordered_map<GlobalString, FullIntrinsicInfo>; | 
|  | IntrinsicMap Map; | 
|  | }; | 
|  |  | 
|  | } // end of namespace Ice | 
|  |  | 
|  | #endif // SUBZERO_SRC_ICEINTRINSICS_H |