【发布时间】: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。我仍然想知道如何用不同长度的字符串替换。