我正在编写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/

10-11 23:08
查看更多