【LLVM编译器系列2】llvm IR中Type类

通过学习LLVM编程手册了解到,核心的LLVM类主要包含Type类,Module类,Value类,User类,Instruction类,Constant类,GlobalValue类,Function类,GlobalVariable类,BasicBlock类和Argument类。程序的检查和转换主要通过核心LLVM类完成的,这些核心类被定义在include/llvm/IR,类的实现在lib/IR目录,编译后的.so库文件名字为libLLVMCore.so。下面分系列章节浅显地聊聊这些类。

Type类概述

Type类是一个superclass,每个Value都具有一个Type类,但是Type类不能直接被实例化,只能通过它的subclass进行使用。某些基本Type类都包含隐藏子类,此类基础类包含:VoidType类,LabelType类,FloatType类和DoubleType类。为什么会被隐藏呢?主要他们没有提供有用的功能,只是简单与其他Type之类区分开。剩余的其他Type都是派生的子类结合,包含:IntegerType类,SequentialType类,ArrayType类,PointerType类,VectorType类,StructType类,Function类,继承关系如下图:

Type类代码介绍

Type中定义TypeID具体定义如下:

enum TypeID {
    // PrimitiveTypes
    HalfTyID = 0,  ///< 16-bit floating point type
    BFloatTyID,    ///< 16-bit floating point type (7-bit significand)
    FloatTyID,     ///< 32-bit floating point type
    DoubleTyID,    ///< 64-bit floating point type
    X86_FP80TyID,  ///< 80-bit floating point type (X87)
    FP128TyID,     ///< 128-bit floating point type (112-bit significand)
    PPC_FP128TyID, ///< 128-bit floating point type (two 64-bits, PowerPC)
    VoidTyID,      ///< type with no size
    LabelTyID,     ///< Labels
    MetadataTyID,  ///< Metadata
    X86_MMXTyID,   ///< MMX vectors (64 bits, X86 specific)
    X86_AMXTyID,   ///< AMX vectors (8192 bits, X86 specific)
    TokenTyID,     ///< Tokens

    // Derived types... see DerivedTypes.h file.
    IntegerTyID,        ///< Arbitrary bit width integers
    FunctionTyID,       ///< Functions
    PointerTyID,        ///< Pointers
    StructTyID,         ///< Structures
    ArrayTyID,          ///< Arrays
    FixedVectorTyID,    ///< Fixed width SIMD vector type
    ScalableVectorTyID, ///< Scalable SIMD vector type
    TypedPointerTyID,   ///< Typed pointer used by some GPU targets
    TargetExtTyID,      ///< Target extension type
  };

isIntegerTy()方法

判断是否为integer类型,代码具体如下:

bool Type::isIntegerTy(unsigned Bitwidth) const {
  return isIntegerTy() && cast<IntegerType>(this)->getBitWidth() == Bitwidth;
}

isFloatingPointTy()方法

判断是否为浮点类型,代码如题如下:

/// Return true if this is a well-behaved IEEE-like type, which has a IEEE
  /// compatible layout as defined by isIEEE(), and does not have unnormal
  /// values
  bool isIEEELikeFPTy() const {
    switch (getTypeID()) {
    case DoubleTyID:
    case FloatTyID:
    case HalfTyID:
    case BFloatTyID:
    case FP128TyID:
      return true;
    default:
      return false;
    }
  }

  /// Return true if this is one of the floating-point types
  bool isFloatingPointTy() const {
    return isIEEELikeFPTy() || getTypeID() == X86_FP80TyID ||
           getTypeID() == PPC_FP128TyID;
  }

isSized()方法

判读Type是否具有确定size。代码如下:

/// 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 {
    // If it's a primitive, it is always sized.
    if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
        getTypeID() == PointerTyID || getTypeID() == X86_MMXTyID ||
        getTypeID() == X86_AMXTyID)
      return true;
    // If it is not something that can have a size (e.g. a function or label),
    // it doesn't have a size.
    if (getTypeID() != StructTyID && getTypeID() != ArrayTyID &&
        !isVectorTy() && getTypeID() != TargetExtTyID)
      return false;
    // Otherwise we have to try harder to decide.
    return isSizedDerivedType(Visited);
  }

派生Type类介绍

  • IntegerType派生类,表示位宽为NumBits的IntegerType。

    IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) {
      assert(NumBits >= MIN_INT_BITS && "bitwidth too small");
      assert(NumBits <= MAX_INT_BITS && "bitwidth too large");
    
      // Check for the built-in integer types
      switch (NumBits) {
      case   1: return cast<IntegerType>(Type::getInt1Ty(C));
      case   8: return cast<IntegerType>(Type::getInt8Ty(C));
      case  16: return cast<IntegerType>(Type::getInt16Ty(C));
      case  32: return cast<IntegerType>(Type::getInt32Ty(C));
      case  64: return cast<IntegerType>(Type::getInt64Ty(C));
      case 128: return cast<IntegerType>(Type::getInt128Ty(C));
      default:
        break;
      }
    
      IntegerType *&Entry = C.pImpl->IntegerTypes[NumBits];
    
      if (!Entry)
        Entry = new (C.pImpl->Alloc) IntegerType(C, NumBits);
    
      return Entry;
    }
  • ArrayType,表示数组类型

//===----------------------------------------------------------------------===//
//                           ArrayType Implementation
//===----------------------------------------------------------------------===//

ArrayType::ArrayType(Type *ElType, uint64_t NumEl)
    : Type(ElType->getContext(), ArrayTyID), ContainedType(ElType),
      NumElements(NumEl) {
  ContainedTys = &ContainedType;
  NumContainedTys = 1;
}

ArrayType *ArrayType::get(Type *ElementType, uint64_t NumElements) {
  assert(isValidElementType(ElementType) && "Invalid type for array element!");

  LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
  ArrayType *&Entry =
    pImpl->ArrayTypes[std::make_pair(ElementType, NumElements)];

  if (!Entry)
    Entry = new (pImpl->Alloc) ArrayType(ElementType, NumElements);
  return Entry;
}

bool ArrayType::isValidElementType(Type *ElemTy) {
  return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
         !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() &&
         !ElemTy->isTokenTy() && !ElemTy->isX86_AMXTy() &&
         !isa<ScalableVectorType>(ElemTy);
}
  • PointerType,表示指针类型

//===----------------------------------------------------------------------===//
//                         PointerType Implementation
//===----------------------------------------------------------------------===//

PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace) {
  assert(EltTy && "Can't get a pointer to <null> type!");
  assert(isValidElementType(EltTy) && "Invalid type for pointer element!");

  // Automatically convert typed pointers to opaque pointers.
  return get(EltTy->getContext(), AddressSpace);
}

PointerType *PointerType::get(LLVMContext &C, unsigned AddressSpace) {
  LLVMContextImpl *CImpl = C.pImpl;

  // Since AddressSpace #0 is the common case, we special case it.
  PointerType *&Entry = AddressSpace == 0 ? CImpl->AS0PointerType
                                          : CImpl->PointerTypes[AddressSpace];

  if (!Entry)
    Entry = new (CImpl->Alloc) PointerType(C, AddressSpace);
  return Entry;
}
  • VectorType,与ArrayType类型相似,主要用于向量计算

//===----------------------------------------------------------------------===//
//                          VectorType Implementation
//===----------------------------------------------------------------------===//

VectorType::VectorType(Type *ElType, unsigned EQ, Type::TypeID TID)
    : Type(ElType->getContext(), TID), ContainedType(ElType),
      ElementQuantity(EQ) {
  ContainedTys = &ContainedType;
  NumContainedTys = 1;
}

VectorType *VectorType::get(Type *ElementType, ElementCount EC) {
  if (EC.isScalable())
    return ScalableVectorType::get(ElementType, EC.getKnownMinValue());
  else
    return FixedVectorType::get(ElementType, EC.getKnownMinValue());
}

bool VectorType::isValidElementType(Type *ElemTy) {
  return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() ||
         ElemTy->isPointerTy() || ElemTy->getTypeID() == TypedPointerTyID;
}

总结:

LLVM中的Value必须具有类型,针对不同type,后面优化PASS处理不尽相同,Type类一旦被创建,就不能被改变。

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值