llvm后端之tblgen寄存器信息

引言

llvm后端采用table-gen语法定义好目标指令描述信息后,可通过llvm-tblgen工具生成源码文件。以x86为例:


llvm-tblgen -gen-register-info X86.td -I ../../../include/ -o=X86GenRegisterInfo.inc     

运行上述命令后就生成了x86的寄存器信息。主要内容如下:

  • 基础枚举信息

1 基础枚举信息

  1. 首先,生成寄存器枚举:
enum {
  NoRegister,
  ... ...
  BH = 4,
  BL = 5,
  ... ...
  BX = 9,
  ... ...
  EBX = 24,
  ... ...
  HBX = 40,
  ... ...
  RBX = 51,
  ... ...
  NUM_TARGET_REGS
};

注: 以上枚举是按照td文件的寄存器定义名称生成,以AX为例,在td文件中有:

class X86Reg<string n, bits<16> Enc, list<Register> subregs = []> : Register<n> {
  let Namespace = "X86";
  let HWEncoding = Enc;
  let SubRegs = subregs;
}
... ...
let SubRegIndices = [sub_8bit, sub_8bit_hi], CoveredBySubRegs = 1 in {
def AX : X86Reg<"ax", 0, [AL,AH]>;
def DX : X86Reg<"dx", 2, [DL,DH]>;
def CX : X86Reg<"cx", 1, [CL,CH]>;
def BX : X86Reg<"bx", 3, [BL,BH]>;
}
... ...
  1. 生成寄存器分类枚举:
enum {
  GR8RegClassID = 0,
  GRH8RegClassID = 1,
  ... ...
  VR512_0_15RegClassID = 117,
};

注:以上枚举是按照td文件的寄存器分类定义名称生成,以GR8RegClassID为例,在td文件有定义:

def GR8 : RegisterClass<"X86", [i8],  8,
                        (add AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL,
                             R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B)> {
  let AltOrders = [(sub GR8, AH, BH, CH, DH)];
  let AltOrderSelect = [{
    return MF.getSubtarget<X86Subtarget>().is64Bit();
  }];
}
  1. 生成子寄存器索引枚举:
enum {
  NoSubRegister,
  sub_8bit,	// 1
  sub_8bit_hi,	// 2
  sub_8bit_hi_phony,	// 3
  sub_16bit,	// 4
  sub_16bit_hi,	// 5
  sub_32bit,	// 6
  sub_mask_0,	// 7
  sub_mask_1,	// 8
  sub_xmm,	// 9
  sub_ymm,	// 10
  NUM_TARGET_SUBREGS
};

注:以上枚举来源于td文件的定义如下:

let Namespace = "X86" in {
  def sub_8bit     : SubRegIndex<8>;
  def sub_8bit_hi  : SubRegIndex<8, 8>;
  def sub_8bit_hi_phony  : SubRegIndex<8, 8>;
  def sub_16bit    : SubRegIndex<16>;
  def sub_16bit_hi : SubRegIndex<16, 16>;
  def sub_32bit    : SubRegIndex<32>;
  def sub_xmm      : SubRegIndex<128>;
  def sub_ymm      : SubRegIndex<256>;
  def sub_mask_0   : SubRegIndex<-1>;
  def sub_mask_1   : SubRegIndex<-1, -1>;
}

2 MC寄存器信息

2.1 寄存器基本信息

寄存器基本信息主要生成如下常量数组:

  • MCPhysReg X86RegDiffLists[]
  • LaneBitmask X86LaneMaskLists[]
  • uint16_t X86SubRegIdxLists
  • MCRegisterInfo::SubRegCoveredBits X86SubRegIdxRanges[]
  • const char X86RegStrings[]
  • MCRegisterDesc X86RegDesc[]
  • MCPhysReg X86RegUnitRoots[][2]

以上数组的关系都是基于X86RegDesc为起点。在llvm源码中,MCRegisterDesc包含五个无符号整数的关键字段:

  • Name:代表寄存器的名称;
  • SubRegs:代表子寄存器列表,指向X86RegDiffLists中的索引值,从该索引往后直到遇到0,是求解子寄存器相应枚举的数字;
  • SuperRegs:代表父寄存器,表示方式与SubRegs类似;
  • SubRegIndices:代表子寄存器索引信息,与SubRegs类似,稍微不同的是指向X86SubRegIdxLists的索引值
  • RegUnits:代表寄存器的寄存器硬件单元列表;
  • RegUnitLaneMasks:

以16位BX寄存器为例,由于BX枚举值为9, 查找X86RegDesc[9],内容如下:

{ 1183, 317, 178, 0, 304, 2 },

注:1183为寄存器名字,字符串X86RegStrings数组中的子字符串&X86RegStrings[1183]刚好为“BX”

  1. 寻找子寄存器

查找X86RegDiffLists[317],得到如下内容:

  /* 317 */ 65532, 65535, 0,

通过BX的枚举值9计算:9+(uint16)65532 = 5(即BL),用上一步结果5计算:5+(uint16)65535=4(即BH);

  1. 寻找子寄存器索引

查找X86SubRegIdxLists[0],得到内容:

  /* 0 */ 1, 2, 0,

数字1,2是子寄存器索引枚举sub_8bit和sub_8bit_hi,索引范围为X86SubRegIdxRanges[1]和X86SubRegIdxRanges[2]。即BL为sub_8bit(Offset=0,Size=8)、BH为sub_8bit_hi(Offset=8,Size=8)。

  1. 寻找父寄存器

查找X86RegDiffLists[178],得到如下内容:

  /* 177 */ 4, 15, 27, 0, 

取得15和27两组值,通过BX的枚举值9计算:15+9 = 24(即EBX),用上一步结果5计算:24+27=51(即RBX);

  1. 寻找寄存器单元

计算scale = 304&0x0f = 0;然后查找查找X86RegDiffLists[304>>4] (即X86RegDiffLists[19]),得到如下内容:

  /* 19 */ 2, 1, 0,

通过BX的枚举值9计算 9 * scale + 2 = 2 ,用上一步结果2 + 1 = 3。X86RegUnitRoots[2]为X86::BH、X86RegUnitRoots[3]为X86::BL。

注:并不是有多少个寄存器就有多少个寄存器单元,例如两个8位BL和BH组成了16位BX、两个16位BX和HBX组成了32位EBX、EBX扩展成64位RBX,有6个寄存器却只有X86::BL、X86::BH、X86::HBX三个寄存器单元

  1. 寻找寄存器单元LaneMask

查找X86LaneMaskLists[2],得出以LaneBitmask::getAll()结尾的内容如下:

  /* 2 */ LaneBitmask(0x00000002), LaneBitmask(0x00000001), LaneBitmask::getAll(),

注:上述内容表示X86::BH和X86::BL对于的LaneMask。其生成规则是按枚举出现顺序将sub_8bit、sub_8bit_hi、sub_8bit_hi_phony、sub_16bit_hi、sub_32bit、sub_xmm、sub_ymm被设置为0x01、0x02、0x04、0x08、0x10、0x20、0x40。另外,sub_16bit比较特殊,它可以由sub_8bit、sub_8bit_hi、sub_8bit_hi_phony组合而成,所以设置为0x07(即0x01 | 0x02 | 0x04)

2.2 寄存器分类信息

寄存器分类信息包括:

  • 寄存器分类所含寄存器枚举数组和BitMask
  • const char X86RegClassStrings[]
  • MCRegisterClass X86MCRegisterClasses[]

以上数组的关系都是基于X86MCRegisterClasses为中心组织起来。在llvm源码中,MCRegisterClass主要包含如下字段:

  • RegsBegin:关于“寄存器分类所含寄存器枚举数组”的迭代器
  • RegSet:关于“寄存器分类所含寄存器的BitMask”的bit序列
  • NameIdx:寄存器分类名称在X86RegClassStrings的索引
  • RegsSize:关于“寄存器分类所含寄存器枚举数组”的长度
  • RegSetSize:关于“寄存器分类所含寄存器的BitMask”的bit序列长度
  • ID:寄存器分类的枚举值
  • CopyCost:寄存器分类的
  • Allocatable:是否可以用于指令分配。

注:CopyCost和Allocatable来源于def RegisterClass的设置let CopyCost = … 和let isAllocatable = …

以X86::GR16RegClassID为例,由于X86::GR16RegClassID枚举值为6,查找X86MCRegisterClasses[6],内容如下:

  { GR16, GR16Bits, 179, 16, sizeof(GR16Bits), X86::GR16RegClassID, 1, true },
  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值