Я хочу изменить индекс GEP по результату предыдущей инструкции - PullRequest
1 голос
/ 27 июня 2019

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

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Обратите внимание на сообщение об ошибке: GEP indexes must be integers.Если вызов функции, которая возвращает int, то он может работать.Это не всегда работает - вы можете вызвать foo () и использовать результат для получения foo () -го элемента массива, но когда вы извлекаете поле структуры, у вас должна быть константа.

Во втором случае вы запрашиваете 784505880-е поле структуры.Это либо ошибка, либо удивительно широкая структура;)

2 голосов
/ 27 июня 2019

AFAIK, использование setOperand() напрямую небезопасно. Вместо этого получите указатель на операнд, который вы хотите изменить, и вызовите GI->replaceUsesOfWith(oldOp, newOp).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...