c++ - 我想根据前一条指令的结果更改 GEP 的索引

标签 c++ llvm

我正在编写一个 LLVM IR pass,它在运行时更改 GetElementPtr 指令的索引操作数。

我成功地用常数整数替换了 GEP 索引。例如, 下面的代码会将 GEP 指令的每个最后索引替换为 0。

// For each instruction in the function
for(inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I){
    // Find GEP instruction
    if(auto *GI = dyn_cast<GetElementPtrInst>(&*I)){
        GI->setOperand(GI->getNumIndices(), ConstantInt::get(Type::getInt32Ty(I->getContext()), 0));
    }
}

结果IR是这样的

Original:  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, i32 0
Replace:  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, i32 0
Original:  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, i32 1
Replace:  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, i32 0

问题是,当我尝试根据运行时指令的结果更改索引时,它失败了。
修改通行证:

for(inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I){
    // Find GEP instruction
    if(auto *GI = dyn_cast<GetElementPtrInst>(&*I)){
        IRBuilder<> Builder(I);
        Instruction* X = Builder.CreateCall(...)
        GI->setOperand(GI->getNumIndices(), X);
    }
}

修改后的结果:

Original:  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, i32 0
Replace:  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, void <badref>
Original:  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, i32 1
Replace:  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, void <badref>
GEP indexes must be integers
  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, void <badref>
GEP indexes must be integers
  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, void <badref>

我还尝试通过以下方式获取返回值的常量整数值 I->setOperand(I->getNumIndices(), ConstantInt::get(Type::getInt32Ty(I->getContext()), cast<ConstantInt>(X)->getZExtValue())); 但也不起作用。

Original:  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, i32 0
Replace:  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, i32 784505880
Original:  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, i32 1
Replace:  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, i32 784506264
Invalid indices for GEP pointer type!
  %7 = getelementptr inbounds %struct.A, %struct.A* %6, i32 0, i32 784505880
Invalid indices for GEP pointer type!
  %9 = getelementptr inbounds %struct.A, %struct.A* %8, i32 0, i32 784506264

我认为原因是无法通过运行结果来设置GEP索引。那我应该怎么做才能在运行时更改 GEP 的每个索引? 我是否需要用一些地址添加和内存访问指令来替换 GEP 指令?

最佳答案

注意错误信息:GEP indexes must be integers。如果调用的是一个返回 int 的函数,那么它就可以工作。它并不总是有效 — 您可以调用 foo() 并使用结果来获取数组的第 foo() 个元素,但是当您检索结构字段时,您必须有一个常量。

在你的第二种情况下,你要求结构的第 784505880 个字段。那要么是一个错误,要么是一个非常宽的结构;)

关于c++ - 我想根据前一条指令的结果更改 GEP 的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56791896/

相关文章:

c++ - 如何检查模板参数是否默认可构造

c++ - 如何在 Python 中检索程序输出?

LLVM IR : C++ API : Typecast from i1 to i32 and i32 to i1

llvm - 指针所有权语义、附加调试信息和 LLVM 中的 "unsigned"用法

c++ - 在 LLVM 中创建文字指针值

c++ - 我如何正确获得BMI?

c++ - 将模板与作用域在函数内的匿名类一起使用

C++ 将函数指针转换为唯一的 “hash” 键

c++ - 如何从 llvm 命令行帮助字符串中隐藏特定的枚举值?

c++ - 从对象或库文件中识别C++的版本(例如c++ 11,c++ 14)