Home | History | Annotate | Download | only in src
      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.
    161     Type getReturnType() const {
    162       assert(NumTypes > 0);
    163       return Signature[0];
    164     }
    165 
    166     /// Returns number of arguments expected.
    167     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