我正在编写LLVM IR传递,该传递在运行时更改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()第一个元素,但是在检索struct字段时,必须有一个常量。
在第二种情况下,您需要结构的784505880th字段。那要么是一个bug,要么是一个非常广泛的结构;)
关于c++ - 我想通过上一条指令的结果更改GEP的索引,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56791896/