通过学习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类一旦被创建,就不能被改变。