【问题标题】:LLVM Pass - Issues replacing a GlobalVariableLLVM Pass - 替换 GlobalVariable 的问题
【发布时间】:2019-09-26 10:56:00
【问题描述】:

我正在尝试编写一个操纵字符串的 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() 要求替换为相同类型。如果我希望替换为不同长度的字符串,我将如何实现?

【问题讨论】:

  • 好的,我发现了类型不匹配的问题。 ConstantDataArray::getString 中的最后一个参数名为 AddNull。如果为真,它将在字符串末尾添加另一个 NULL。我仍然想知道如何用不同长度的字符串替换。

标签: llvm llvm-ir llvm-gcc


【解决方案1】:

您不能用不同类型的对象替换。但是,您可以强制转换 GlobalVariable 以获得正确的类型。你想要的是……

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

...除了那不会编译,因为第二个参数必须是 PointerType。您总是可以添加另一个级别的强制转换,使代码不那么清晰,但编译器更快乐:

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

我发现 all 可变长度数组对用户使用 0 长度数组很有帮助,并且 always 将常量转换为该数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    相关资源
    最近更新 更多