I am trying to write an LLVM pass which manipulates strings.
After iterating all the GlobalVariable objects and picking out the strings, I get the string data, perform the manipulation, create a new GlobalVariable and then use replaceAllUsesWith()
to replace the old with the new. Sounds simple enough...
However, I am getting an assert error, telling me that the replacement should be the same type. I have not changed the length of the string, so I don't know why the type would be different. A cut down version of the code is below.
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);
}
Note: I've hand typed this code, so it may not compile, but it should serve as an illustration of what I'm trying to achieve and how I'm trying to achieve it.
For some reason, the new GlobalVariable has a different type. Printing the types at runtime yields:
gv->getType() = [36 x i8]*
newGv->getType() = [37 * x i8]*
The size of both strings are 36 chars. Why is the type of the new GlobalVariable different, even though the string length has not changed? Why has an extra element been added?
Also, replaceAllUsesWith()
requires that the replacement be same type. If I wanted the replacement to be string of a different length, how would I achieve that?