[llvm] [SandboxIR] Implement SandboxIR Type (PR #106294)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 29 15:51:52 PDT 2024


================
@@ -0,0 +1,288 @@
+//===- llvm/SandboxIR/Type.h - Classes for handling data types --*- 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 is a thin wrapper over llvm::Type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SANDBOXIR_TYPE_H
+#define LLVM_SANDBOXIR_TYPE_H
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm::sandboxir {
+
+class Context;
+// Forward declare friend classes for MSVC.
+class PointerType;
+class VectorType;
+class FunctionType;
+#define DEF_INSTR(ID, OPCODE, CLASS) class CLASS;
+#include "llvm/SandboxIR/SandboxIRValues.def"
+
+/// Just like llvm::Type these are immutable, unique, never get freed and can
+/// only be created via static factory methods.
+class Type {
+protected:
+  llvm::Type *LLVMTy;
+  friend class VectorType;   // For LLVMTy.
+  friend class PointerType;  // For LLVMTy.
+  friend class FunctionType; // For LLVMTy.
+  friend class Function;     // For LLVMTy.
+  friend class CallBase;     // For LLVMTy.
+  friend class ConstantInt;  // For LLVMTy.
+  // Friend all instruction classes because `create()` functions use LLVMTy.
+#define DEF_INSTR(ID, OPCODE, CLASS) friend class CLASS;
+  // TODO: Friend DEF_CONST()
+#include "llvm/SandboxIR/SandboxIRValues.def"
+  Context &Ctx;
+
+  Type(llvm::Type *LLVMTy, Context &Ctx) : LLVMTy(LLVMTy), Ctx(Ctx) {}
+  friend class Context; // For constructor and ~Type().
+  ~Type() = default;
+
+public:
+  Context &getContext() const { return Ctx; }
+
+  /// Return true if this is 'void'.
+  bool isVoidTy() const { return LLVMTy->isVoidTy(); }
+
+  /// Return true if this is 'half', a 16-bit IEEE fp type.
+  bool isHalfTy() const { return LLVMTy->isHalfTy(); }
+
+  /// Return true if this is 'bfloat', a 16-bit bfloat type.
+  bool isBFloatTy() const { return LLVMTy->isBFloatTy(); }
+
+  /// Return true if this is a 16-bit float type.
+  bool is16bitFPTy() const { return LLVMTy->is16bitFPTy(); }
+
+  /// Return true if this is 'float', a 32-bit IEEE fp type.
+  bool isFloatTy() const { return LLVMTy->isFloatTy(); }
+
+  /// Return true if this is 'double', a 64-bit IEEE fp type.
+  bool isDoubleTy() const { return LLVMTy->isDoubleTy(); }
+
+  /// Return true if this is x86 long double.
+  bool isX86_FP80Ty() const { return LLVMTy->isX86_FP80Ty(); }
+
+  /// Return true if this is 'fp128'.
+  bool isFP128Ty() const { return LLVMTy->isFP128Ty(); }
+
+  /// Return true if this is powerpc long double.
+  bool isPPC_FP128Ty() const { return LLVMTy->isPPC_FP128Ty(); }
+
+  /// Return true if this is a well-behaved IEEE-like type, which has a IEEE
+  /// compatible layout as defined by APFloat::isIEEE(), and does not have
+  /// non-IEEE values, such as x86_fp80's unnormal values.
+  bool isIEEELikeFPTy() const { return LLVMTy->isIEEELikeFPTy(); }
+
+  /// Return true if this is one of the floating-point types
+  bool isFloatingPointTy() const { return LLVMTy->isFloatingPointTy(); }
+
+  /// Returns true if this is a floating-point type that is an unevaluated sum
+  /// of multiple floating-point units.
+  /// An example of such a type is ppc_fp128, also known as double-double, which
+  /// consists of two IEEE 754 doubles.
+  bool isMultiUnitFPType() const { return LLVMTy->isMultiUnitFPType(); }
+
+  const fltSemantics &getFltSemantics() const {
+    return LLVMTy->getFltSemantics();
+  }
+
+  /// Return true if this is X86 AMX.
+  bool isX86_AMXTy() const { return LLVMTy->isX86_AMXTy(); }
+
+  /// Return true if this is a target extension type.
+  bool isTargetExtTy() const { return LLVMTy->isTargetExtTy(); }
+
+  /// Return true if this is a target extension type with a scalable layout.
+  bool isScalableTargetExtTy() const { return LLVMTy->isScalableTargetExtTy(); }
+
+  /// Return true if this is a type whose size is a known multiple of vscale.
+  bool isScalableTy() const { return LLVMTy->isScalableTy(); }
+
+  /// Return true if this is a FP type or a vector of FP.
+  bool isFPOrFPVectorTy() const { return LLVMTy->isFPOrFPVectorTy(); }
+
+  /// Return true if this is 'label'.
+  bool isLabelTy() const { return LLVMTy->isLabelTy(); }
+
+  /// Return true if this is 'metadata'.
+  bool isMetadataTy() const { return LLVMTy->isMetadataTy(); }
+
+  /// Return true if this is 'token'.
+  bool isTokenTy() const { return LLVMTy->isTokenTy(); }
+
+  /// True if this is an instance of IntegerType.
+  bool isIntegerTy() const { return LLVMTy->isIntegerTy(); }
+
+  /// Return true if this is an IntegerType of the given width.
+  bool isIntegerTy(unsigned Bitwidth) const {
+    return LLVMTy->isIntegerTy(Bitwidth);
+  }
+
+  /// Return true if this is an integer type or a vector of integer types.
+  bool isIntOrIntVectorTy() const { return LLVMTy->isIntOrIntVectorTy(); }
+
+  /// Return true if this is an integer type or a vector of integer types of
+  /// the given width.
+  bool isIntOrIntVectorTy(unsigned BitWidth) const {
+    return LLVMTy->isIntOrIntVectorTy(BitWidth);
+  }
+
+  /// Return true if this is an integer type or a pointer type.
+  bool isIntOrPtrTy() const { return LLVMTy->isIntOrPtrTy(); }
+
+  /// True if this is an instance of FunctionType.
+  bool isFunctionTy() const { return LLVMTy->isFunctionTy(); }
+
+  /// True if this is an instance of StructType.
+  bool isStructTy() const { return LLVMTy->isStructTy(); }
+
+  /// True if this is an instance of ArrayType.
+  bool isArrayTy() const { return LLVMTy->isArrayTy(); }
+
+  /// True if this is an instance of PointerType.
+  bool isPointerTy() const { return LLVMTy->isPointerTy(); }
+
+  /// Return true if this is a pointer type or a vector of pointer types.
+  bool isPtrOrPtrVectorTy() const { return LLVMTy->isPtrOrPtrVectorTy(); }
+
+  /// True if this is an instance of VectorType.
+  inline bool isVectorTy() const { return LLVMTy->isVectorTy(); }
+
+  /// Return true if this type could be converted with a lossless BitCast to
+  /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the
+  /// same size only where no re-interpretation of the bits is done.
+  /// Determine if this type could be losslessly bitcast to Ty
+  bool canLosslesslyBitCastTo(Type *Ty) const {
+    return LLVMTy->canLosslesslyBitCastTo(Ty->LLVMTy);
+  }
+
+  /// Return true if this type is empty, that is, it has no elements or all of
+  /// its elements are empty.
+  bool isEmptyTy() const { return LLVMTy->isEmptyTy(); }
+
+  /// Return true if the type is "first class", meaning it is a valid type for a
+  /// Value.
+  bool isFirstClassType() const { return LLVMTy->isFirstClassType(); }
+
+  /// Return true if the type is a valid type for a register in codegen. This
+  /// includes all first-class types except struct and array types.
+  bool isSingleValueType() const { return LLVMTy->isSingleValueType(); }
+
+  /// Return true if the type is an aggregate type. This means it is valid as
+  /// the first operand of an insertvalue or extractvalue instruction. This
+  /// includes struct and array types, but does not include vector types.
+  bool isAggregateType() const { return LLVMTy->isAggregateType(); }
+
+  /// Return true if it makes sense to take the size of this type. To get the
+  /// actual size for a particular target, it is reasonable to use the
+  /// DataLayout subsystem to do this.
+  bool isSized(SmallPtrSetImpl<Type *> *Visited = nullptr) const {
+    SmallPtrSet<llvm::Type *, 8> LLVMVisited;
+    LLVMVisited.reserve(Visited->size());
+    for (Type *Ty : *Visited)
+      LLVMVisited.insert(Ty->LLVMTy);
+    return LLVMTy->isSized(&LLVMVisited);
+  }
+
+  /// Return the basic size of this type if it is a primitive type. These are
+  /// fixed by LLVM and are not target-dependent.
+  /// This will return zero if the type does not have a size or is not a
+  /// primitive type.
+  ///
+  /// If this is a scalable vector type, the scalable property will be set and
+  /// the runtime size will be a positive integer multiple of the base size.
+  ///
+  /// Note that this may not reflect the size of memory allocated for an
+  /// instance of the type or the number of bytes that are written when an
+  /// instance of the type is stored to memory. The DataLayout class provides
+  /// additional query functions to provide this information.
+  ///
+  TypeSize getPrimitiveSizeInBits() const {
+    return LLVMTy->getPrimitiveSizeInBits();
+  }
+
+  /// If this is a vector type, return the getPrimitiveSizeInBits value for the
+  /// element type. Otherwise return the getPrimitiveSizeInBits value for this
+  /// type.
+  unsigned getScalarSizeInBits() const { return LLVMTy->getScalarSizeInBits(); }
+
+  /// Return the width of the mantissa of this type. This is only valid on
+  /// floating-point types. If the FP type does not have a stable mantissa (e.g.
+  /// ppc long double), this method returns -1.
+  int getFPMantissaWidth() const { return LLVMTy->getFPMantissaWidth(); }
+
+  /// Return whether the type is IEEE compatible, as defined by the eponymous
+  /// method in APFloat.
+  bool isIEEE() const { return LLVMTy->isIEEE(); }
+
+  /// If this is a vector type, return the element type, otherwise return
+  /// 'this'.
+  Type *getScalarType() const;
+
+  // TODO: ADD MISSING
+
+  static Type *getInt64Ty(Context &Ctx);
+  static Type *getInt32Ty(Context &Ctx);
+  static Type *getInt16Ty(Context &Ctx);
+  static Type *getInt8Ty(Context &Ctx);
+  static Type *getInt1Ty(Context &Ctx);
+  static Type *getDoubleTy(Context &Ctx);
+  static Type *getFloatTy(Context &Ctx);
+  // TODO: missing get*
+
+  /// Get the address space of this pointer or pointer vector type.
+  inline unsigned getPointerAddressSpace() const {
+    return LLVMTy->getPointerAddressSpace();
+  }
+
+#ifndef NDEBUG
+  void dumpOS(raw_ostream &OS) { LLVMTy->print(OS); }
+  LLVM_DUMP_METHOD void dump() {
+    dumpOS(dbgs());
+    dbgs() << "\n";
+  }
+#endif // NDEBUG
----------------
vporpo wrote:

Hmm we could wrap that too, but I don't think I have any use for it for now. In LLVM IR it seems to be used in a couple of places though.

https://github.com/llvm/llvm-project/pull/106294


More information about the llvm-commits mailing list