Я пишу проход IR LLVM, который изменяет индексный операнд инструкции 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 на некоторые дополнения адресов и инструкцию доступа к памяти?