llvm libLLVMCore源码分析 01 - Type Class

源码路径

llvm\include\llvm\IR\Type.h

llvm\include\llvm\IR\DerivedTypes.h

llvm类型系统

llvm类型系统是llvm IR最重要的特性之一,是llvm IR和普通的三地址码的重要区别,是一系列的基于IR的优化的基础。以下面的源代码为例:

// type.cpp

int add1(int a, int b) {
	return a + b;
}

使用命令"clang -S -emit-llvm type.cpp -o type.ll",可以生成对应的llvm IR,可以看到llvm的IR中会使用类型i32来修饰操作数。

; ModuleID = 'type.cpp'
source_filename = "type.cpp"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @_Z4add1ii(i32 %a, i32 %b) #0 {
entry:
  %a.addr = alloca i32, align 4
  %b.addr = alloca i32, align 4
  store i32 %a, i32* %a.addr, align 4
  store i32 %b, i32* %b.addr, align 4
  %0 = load i32, i32* %a.addr, align 4
  %1 = load i32, i32* %b.addr, align 4
  %add = add nsw i32 %0, %1
  ret i32 %add
}

llvm Type class

在llvm中,使用Type类来实现llvm类型系统,Type的所有类型如下列枚举定义,其中PrimitiveTypes是没有子类的类型,没有子类的原因是因为不需要。

  enum TypeID {
    // PrimitiveTypes - make sure LastPrimitiveTyID stays up to date.
    VoidTyID = 0,    ///<  0: type with no size
    HalfTyID,        ///<  1: 16-bit floating point type
    FloatTyID,       ///<  2: 32-bit floating point type
    DoubleTyID,      ///<  3: 64-bit floating point type
    X86_FP80TyID,    ///<  4: 80-bit floating point type (X87)
    FP128TyID,       ///<  5: 128-bit floating point type (112-bit mantissa)
    PPC_FP128TyID,   ///<  6: 128-bit floating point type (two 64-bits, PowerPC)
    LabelTyID,       ///<  7: Labels
    MetadataTyID,    ///<  8: Metadata
    X86_MMXTyID,     ///<  9: MMX vectors (64 bits, X86 specific)
    TokenTyID,       ///< 10: Tokens

    // Derived types... see DerivedTypes.h file.
    // Make sure FirstDerivedTyID stays up to date!
    IntegerTyID,     ///< 11: Arbitrary bit width integers
    FunctionTyID,    ///< 12: Functions
    StructTyID,      ///< 13: Structures
    ArrayTyID,       ///< 14: Arrays
    PointerTyID,     ///< 15: Pointers
    VectorTyID       ///< 16: SIMD 'packed' format, or other vector type
  };

Type类的继承树如下图所示:

llvm::Type

所有Type类型的父类,由于构造函数被声明为protected,所以不能被直接实例化。

llvm::IntegerType

任意位宽的integer类型。位宽的范围为[IntegerType::MIN_INT_BITS (1) ,IntegerType::MAX_INT_BITS]。

llvm::FunctionType

函数签名,包含了1个返回值类型和1个参数类型列表。

语法:<returntype> (<parameter list>)

示例:

i32 (i32)传入1个i32, 返回i32
float (i16, i32 *) *函数指针类型,传入1个i16和1个i32的指针, 返回float.
i32 (i8*, ...)变长函数,至少传入1个i8 的指针, 放回i32,既llvm中printf的函数签名。
{i32, i32} (i32)传入1个i32, 返回1个由2个i32组成的结构体

llvm::PointerType

引用内存中的对象,表示Memory Location。PointerType有1个可选的address space属性,默认为0,非0的address space的语义是实现自定义的(target-specific)的。

语法:

<type> *

ptr

示例:

[4 x i32]*长度为4的i32数组指针
i32 (i32*) *函数指针,传入1个i32*, 返回i32.
i32 addrspace(5)*address space 5中的指向i32的指针
ptr不透明指针.
ptr addrspace(5)address space 5中的不透明指针

llvm::StructureType

内存中数据成员的集合,数据成员必须是有size属性的Type。

内存中的Structure访问:通过"getelementptr"指令获取数据成员指针,再对指针使用load和store指令。

寄存器中的Structure访问:使用extractvalue和insertvalue指令

Structure可以是"packed" Structure,按照1byte对齐;也可以是"no-packed" Structure,数据成员间的padding由module中的DataLayout字符串决定。

Structure可以是"literal"的,既使用inline的形式定义,例如:{i32, i32}*;也可以是"identified"的,既使用名字进行定义,例如:

%T1 = type { <type list> }     ; 定义no-packed identified structure T1
%T2 = type <{ <type list> }>   ; 定义packed identified structure T2

Structure也可以是不透明的,通常用于前置声明,语法如下:

%X = type opaque  ; 定义有名字的opaque structure X
%52 = type opaque ; 定义没有名字的opaque structure 52

llvm::ArrayType

ArrayType是1种将元素在内存中顺序排列的类型,有2个属性:size和元素类型。

语法:

[<# elements> x <elementtype>]

其中elementtype是任意有size属性的Type。

示例:

[40 x i32]长度为40的32位整数Array
[41 x i32]长度为41的32位整数Array
[4 x i8]长度为4的8位整数Array
[3 x [4 x i32]]3x4的32位整数Array
[12 x [10 x float]]12x10的单精度浮点Array
[2 x [3 x [4 x i16]]]2x3x4的16位整数Array

llvm::VectorType

VectorType表示元素的矢量,用于SIMD(单指令多数据),有3个属性:size,元素类型(必须是primitive类型),是否可扩展(scalable)。如果VectorType是可扩展的,则Vector的实际长度 = N * size。

当VectorType的长度以byte为单位时,VectorType在内存中的排布和ArrayType相同。当VectorType的长度不以byte为单位时,需要使用bitcase指令完成VectorType到IntegerType的相互转换,示例如下(大端):

%val = bitcast <4 x i4> <i4 1, i4 2, i4 3, i4 5> to i16

; Bitcasting from a vector to an integral type can be seen as
; concatenating the values:
;   %val now has the hexadecimal value 0x1235.

store i16 %val, i16* %ptr

; In memory the content will be (8-bit addressing):
;
;    [%ptr + 0]: 00010010  (0x12)
;    [%ptr + 1]: 00110101  (0x35)

语法:

< <# elements> x <elementtype> >          ; Fixed-length vector
< vscale x <# elements> x <elementtype> > ; Scalable vector

其中elementtype只能是整数,浮点数,指针。

示例:

<4 x i32>长度为4的32位整数Vector
<8 x float>长度为8的32位单精度浮点数Vector
<2 x i64>长度为2的64位整数Vector
<4 x i64*>长度为2的64位整数指针Vector
<vscale x 4 x i32>长度为4的整数倍的32位整数Vector

参考材料

LLVM Language Reference Manual — LLVM 15.0.0git documentation

LLVM Programmer’s Manual — LLVM 15.0.0git documentation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值