//===- Intrinsics.h - LLVM Intrinsic Function Handling ----------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// This file defines a set of enums which allow processing of intrinsic
 
// functions.  Values of these enum types are returned by
 
// Function::getIntrinsicID.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_IR_INTRINSICS_H
 
#define LLVM_IR_INTRINSICS_H
 
 
 
#include "llvm/ADT/ArrayRef.h"
 
#include "llvm/Support/TypeSize.h"
 
#include <optional>
 
#include <string>
 
 
 
namespace llvm {
 
 
 
class Type;
 
class FunctionType;
 
class Function;
 
class LLVMContext;
 
class Module;
 
class AttributeList;
 
 
 
/// This namespace contains an enum with a value for every intrinsic/builtin
 
/// function known by LLVM. The enum values are returned by
 
/// Function::getIntrinsicID().
 
namespace Intrinsic {
 
  // Abstraction for the arguments of the noalias intrinsics
 
  static const int NoAliasScopeDeclScopeArg = 0;
 
 
 
  // Intrinsic ID type. This is an opaque typedef to facilitate splitting up
 
  // the enum into target-specific enums.
 
  typedef unsigned ID;
 
 
 
  enum IndependentIntrinsics : unsigned {
 
    not_intrinsic = 0, // Must be zero
 
 
 
  // Get the intrinsic enums generated from Intrinsics.td
 
#define GET_INTRINSIC_ENUM_VALUES
 
#include "llvm/IR/IntrinsicEnums.inc"
 
#undef GET_INTRINSIC_ENUM_VALUES
 
  };
 
 
 
  /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
 
  /// Note, this version is for intrinsics with no overloads.  Use the other
 
  /// version of getName if overloads are required.
 
  StringRef getName(ID id);
 
 
 
  /// Return the LLVM name for an intrinsic, without encoded types for
 
  /// overloading, such as "llvm.ssa.copy".
 
  StringRef getBaseName(ID id);
 
 
 
  /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx" or
 
  /// "llvm.ssa.copy.p0s_s.1". Note, this version of getName supports overloads.
 
  /// This is less efficient than the StringRef version of this function.  If no
 
  /// overloads are required, it is safe to use this version, but better to use
 
  /// the StringRef version. If one of the types is based on an unnamed type, a
 
  /// function type will be computed. Providing FT will avoid this computation.
 
  std::string getName(ID Id, ArrayRef<Type *> Tys, Module *M,
 
                      FunctionType *FT = nullptr);
 
 
 
  /// Return the LLVM name for an intrinsic. This is a special version only to
 
  /// be used by LLVMIntrinsicCopyOverloadedName. It only supports overloads
 
  /// based on named types.
 
  std::string getNameNoUnnamedTypes(ID Id, ArrayRef<Type *> Tys);
 
 
 
  /// Return the function type for an intrinsic.
 
  FunctionType *getType(LLVMContext &Context, ID id,
 
                        ArrayRef<Type *> Tys = std::nullopt);
 
 
 
  /// Returns true if the intrinsic can be overloaded.
 
  bool isOverloaded(ID id);
 
 
 
  /// Return the attributes for an intrinsic.
 
  AttributeList getAttributes(LLVMContext &C, ID id);
 
 
 
  /// Create or insert an LLVM Function declaration for an intrinsic, and return
 
  /// it.
 
  ///
 
  /// The Tys parameter is for intrinsics with overloaded types (e.g., those
 
  /// using iAny, fAny, vAny, or iPTRAny).  For a declaration of an overloaded
 
  /// intrinsic, Tys must provide exactly one type for each overloaded type in
 
  /// the intrinsic.
 
  Function *getDeclaration(Module *M, ID id,
 
                           ArrayRef<Type *> Tys = std::nullopt);
 
 
 
  /// Looks up Name in NameTable via binary search. NameTable must be sorted
 
  /// and all entries must start with "llvm.".  If NameTable contains an exact
 
  /// match for Name or a prefix of Name followed by a dot, its index in
 
  /// NameTable is returned. Otherwise, -1 is returned.
 
  int lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
 
                                StringRef Name);
 
 
 
  /// Map a Clang builtin name to an intrinsic ID.
 
  ID getIntrinsicForClangBuiltin(const char *Prefix, StringRef BuiltinName);
 
 
 
  /// Map a MS builtin name to an intrinsic ID.
 
  ID getIntrinsicForMSBuiltin(const char *Prefix, StringRef BuiltinName);
 
 
 
  /// This is a type descriptor which explains the type requirements of an
 
  /// intrinsic. This is returned by getIntrinsicInfoTableEntries.
 
  struct IITDescriptor {
 
    enum IITDescriptorKind {
 
      Void,
 
      VarArg,
 
      MMX,
 
      Token,
 
      Metadata,
 
      Half,
 
      BFloat,
 
      Float,
 
      Double,
 
      Quad,
 
      Integer,
 
      Vector,
 
      Pointer,
 
      Struct,
 
      Argument,
 
      ExtendArgument,
 
      TruncArgument,
 
      HalfVecArgument,
 
      SameVecWidthArgument,
 
      PtrToArgument,
 
      PtrToElt,
 
      VecOfAnyPtrsToElt,
 
      VecElementArgument,
 
      Subdivide2Argument,
 
      Subdivide4Argument,
 
      VecOfBitcastsToInt,
 
      AMX,
 
      PPCQuad,
 
      AnyPtrToElt,
 
    } Kind;
 
 
 
    union {
 
      unsigned Integer_Width;
 
      unsigned Float_Width;
 
      unsigned Pointer_AddressSpace;
 
      unsigned Struct_NumElements;
 
      unsigned Argument_Info;
 
      ElementCount Vector_Width;
 
    };
 
 
 
    enum ArgKind {
 
      AK_Any,
 
      AK_AnyInteger,
 
      AK_AnyFloat,
 
      AK_AnyVector,
 
      AK_AnyPointer,
 
      AK_MatchType = 7
 
    };
 
 
 
    unsigned getArgumentNumber() const {
 
      assert(Kind == Argument || Kind == ExtendArgument ||
 
             Kind == TruncArgument || Kind == HalfVecArgument ||
 
             Kind == SameVecWidthArgument || Kind == PtrToArgument ||
 
             Kind == PtrToElt || Kind == VecElementArgument ||
 
             Kind == Subdivide2Argument || Kind == Subdivide4Argument ||
 
             Kind == VecOfBitcastsToInt);
 
      return Argument_Info >> 3;
 
    }
 
    ArgKind getArgumentKind() const {
 
      assert(Kind == Argument || Kind == ExtendArgument ||
 
             Kind == TruncArgument || Kind == HalfVecArgument ||
 
             Kind == SameVecWidthArgument || Kind == PtrToArgument ||
 
             Kind == VecElementArgument || Kind == Subdivide2Argument ||
 
             Kind == Subdivide4Argument || Kind == VecOfBitcastsToInt);
 
      return (ArgKind)(Argument_Info & 7);
 
    }
 
 
 
    // VecOfAnyPtrsToElt and AnyPtrToElt uses both an overloaded argument (for
 
    // address space) and a reference argument (for matching vector width and
 
    // element types)
 
    unsigned getOverloadArgNumber() const {
 
      assert(Kind == VecOfAnyPtrsToElt || Kind == AnyPtrToElt);
 
      return Argument_Info >> 16;
 
    }
 
    unsigned getRefArgNumber() const {
 
      assert(Kind == VecOfAnyPtrsToElt || Kind == AnyPtrToElt);
 
      return Argument_Info & 0xFFFF;
 
    }
 
 
 
    static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
 
      IITDescriptor Result = { K, { Field } };
 
      return Result;
 
    }
 
 
 
    static IITDescriptor get(IITDescriptorKind K, unsigned short Hi,
 
                             unsigned short Lo) {
 
      unsigned Field = Hi << 16 | Lo;
 
      IITDescriptor Result = {K, {Field}};
 
      return Result;
 
    }
 
 
 
    static IITDescriptor getVector(unsigned Width, bool IsScalable) {
 
      IITDescriptor Result = {Vector, {0}};
 
      Result.Vector_Width = ElementCount::get(Width, IsScalable);
 
      return Result;
 
    }
 
  };
 
 
 
  /// Return the IIT table descriptor for the specified intrinsic into an array
 
  /// of IITDescriptors.
 
  void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
 
 
 
  enum MatchIntrinsicTypesResult {
 
    MatchIntrinsicTypes_Match = 0,
 
    MatchIntrinsicTypes_NoMatchRet = 1,
 
    MatchIntrinsicTypes_NoMatchArg = 2,
 
  };
 
 
 
  /// Match the specified function type with the type constraints specified by
 
  /// the .td file. If the given type is an overloaded type it is pushed to the
 
  /// ArgTys vector.
 
  ///
 
  /// Returns false if the given type matches with the constraints, true
 
  /// otherwise.
 
  MatchIntrinsicTypesResult
 
  matchIntrinsicSignature(FunctionType *FTy, ArrayRef<IITDescriptor> &Infos,
 
                          SmallVectorImpl<Type *> &ArgTys);
 
 
 
  /// Verify if the intrinsic has variable arguments. This method is intended to
 
  /// be called after all the fixed arguments have been matched first.
 
  ///
 
  /// This method returns true on error.
 
  bool matchIntrinsicVarArg(bool isVarArg, ArrayRef<IITDescriptor> &Infos);
 
 
 
  /// Gets the type arguments of an intrinsic call by matching type contraints
 
  /// specified by the .td file. The overloaded types are pushed into the
 
  /// AgTys vector.
 
  ///
 
  /// Returns false if the given function is not a valid intrinsic call.
 
  bool getIntrinsicSignature(Function *F, SmallVectorImpl<Type *> &ArgTys);
 
 
 
  // Checks if the intrinsic name matches with its signature and if not
 
  // returns the declaration with the same signature and remangled name.
 
  // An existing GlobalValue with the wanted name but with a wrong prototype
 
  // or of the wrong kind will be renamed by adding ".renamed" to the name.
 
  std::optional<Function *> remangleIntrinsicFunction(Function *F);
 
 
 
} // End Intrinsic namespace
 
 
 
} // End llvm namespace
 
 
 
#endif