//===- 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; IntrinsicMap Map; }; } // end of namespace Ice #endif // SUBZERO_SRC_ICEINTRINSICS_H