Value 表示了 LLVM IR 中需要通过指令运行得到的值。 它是 Instruction 和 Function 的父类。每一个值都持有一个 Type 指针(表达了在 IR 中的值类型)和一个 Use 指针(指向了一个 use list)。
User (Value 的子类) 定义了使用值的接口。Instruction 和 Constants 这两个常见类都是 User 的子类。
Use 表示了了 User 实例对 Value 的使用。
有利于
相关源码如下
void *User::operator new(size_t Size) {
// Allocate space for a single Use*
void *Storage = ::operator new(Size + sizeof(Use *));
Use **HungOffOperandList = static_cast
这种 new 下, User 的 HasHungOffUses 为 true
可以看到在分配 User 的空间时, 还额外地分配了一个 Use 的空间。这样获得一块可以放一个user+一个use 指针的空间。
低地址空间用于存放 Use 指针, 高地址空间存放 User。
初始化了 User 的一些值, 并设置 Use 指针为 nullptr
.-------... | User '-------''' | v .---.---.---.---... | P | P | P | P | '---'---'---'---'''
两个 placement new 都调用了 allocateFixedOperandUser 方法
void *User::operator new(size_t Size, unsigned Us) {
return allocateFixedOperandUser(Size, Us, 0);
}
void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) {
return allocateFixedOperandUser(Size, Us, DescBytes);
}
allocateFixedOperandUser 方法如下
void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
unsigned DescBytes) {
assert(Us < (1u << NumUserOperandsBits) && "Too many operands");
static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below");
unsigned DescBytesToAllocate =
DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo));
assert(DescBytesToAllocate % sizeof(void *) == 0 &&
"We need this to satisfy alignment constraints for Uses");
uint8_t *Storage = static_cast(
::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate));
Use *Start = reinterpret_cast
这种 new 下, User 的 HasHungOffUses 为 false
整体上, 这个函数会额外分配 Us 个 Use 实例和描述字符的空间。
低地址存放描述字符, 随后存放了 Use 实例, 最后是分配给 User 实例的空间。
又初始化了 User 的部分属性。 构造了 Us 个 Use 实例。
...---.---.---.---.-------... | P | P | P | P | User '''---'---'---'---'-------'''
对于 HungOff 式 User , 提供了以下方法:
const Use *getHungOffOperands() const {
return *(reinterpret_cast(this) - 1);
}
Use *&getHungOffOperands() { return *(reinterpret_cast
对于 Intrusive 式 User , 提供了以下方法:
const Use *getIntrusiveOperands() const {
return reinterpret_cast(this) - NumUserOperands;
}
Use *getIntrusiveOperands() {
return reinterpret_cast
对于Value , 可以使用 users 方法遍历所有 user
深入浅出 LLVM之 Value 、User 、Use 源码解析 - 知乎
LLVM Programmer’s Manual — LLVM 19.0.0git documentation