LLVM Pass - проблемы, заменяющие GlobalVariable - PullRequest
0 голосов
/ 26 сентября 2019

Я пытаюсь написать проход LLVM, который манипулирует строками.

После итерации всех объектов GlobalVariable и выбора строк я получаю строковые данные, выполняю манипуляции, создаю новую GlobalVariable и затем использую replaceAllUsesWith() для замены старого новым.Звучит достаточно просто ...

Однако я получаю ошибку подтверждения, сообщающую, что замена должна быть того же типа.Я не изменил длину строки, поэтому я не знаю, почему тип будет другим.Ниже приведена сокращенная версия кода.

for (Module::global_iterator gi = M.global_begin(), ge = M.global_end(); gi != ge; gi++) {
    GlobalVariable *gv = *gi;
    ConstantDataSequential *cdata = dyn_cast<ConstantDataSequential>(gv->getInitializer());

    std::string orig = "";

    if (cdata->isString() {
        orig = cdata->getAsString();
    } else if (cdata->isCString() {
        orig = cdata->getAsCString();
    } else {
        continue;
    }

    // string returned has the same length, but different contents
    std::string modified = manipulateString(orig);

    std::ostringstream oss;
    oss << gv->getName() << "Modified" ;

    Constant *cMod = ConstantDataArray::getString(M.getContext(), modified, true);

    GlobalVariable *newGv = new GlobalVariable(M, 
                                               cMod->getType(), 
                                               true, 
                                               GlobalValue::ExternalLinkage, 
                                               cMod, 
                                               oss.str());

    gv->replaceAllUsesWith(newGv);
}

Примечание. Я вручную набрал этот код, поэтому он может не компилироваться, но он должен служить иллюстрацией того, что япытаюсь достичь и как я пытаюсь достичь этого.

По какой-то причине новый GlobalVariable имеет другой тип.Печать типов во время выполнения дает:

gv->getType() = [36 x i8]*
newGv->getType() = [37 * x i8]*

Размер обеих строк составляет 36 символов.Почему тип нового GlobalVariable отличается, хотя длина строки не изменилась?Почему был добавлен дополнительный элемент?

Кроме того, replaceAllUsesWith() требует, чтобы замена была того же типа.Если бы я хотел, чтобы замена была строкой другой длины, как бы я этого достиг?

1 Ответ

1 голос
/ 27 сентября 2019

Нельзя заменить объектом другого типа.Однако вы можете привести GlobalVariable, чтобы иметь правильный тип.То, что вы хотите, это ...

ConstantExpr::getPointerCast(newGv, gv->getType());

... за исключением того, что это не скомпилируется, потому что второй аргумент должен быть PointerType.Вы всегда можете добавить другой уровень приведения, делая код менее понятным, но компилятор более доволен:

ConstantExpr::getPointerCast(newGv, cast<PointerType>(gv->getType()));

Я считаю, что это полезно для пользовательских массивов 0 для all variable-длины массивов и всегда приводят константы к этому.

...