This is an archive of the discontinued LLVM Phabricator instance.

[remangleIntrinsicFunction] Detect and resolve name clash
ClosedPublic

Authored by jeroen.dobbelaere on Jun 29 2021, 7:17 AM.

Details

Summary

It is possible that the remangled name for an intrinsic already exists with a different (and wrong) prototype within the module.
As the bitcode reader keeps both versions of all remangled intrinsics around for a longer time, this can result in a
crash, as can be seen in https://bugs.llvm.org/show_bug.cgi?id=50923

This patch makes 'remangleIntrinsicFunction' aware of this situation. When it is detected, it moves the version with the wrong prototype to a different name. That version will be removed anyway once the module is completely loaded.

With thanks to @asbirlea for reporting this issue when trying out an lto build with the full restrict patches, and @efriedma for suggesting a sane resolution mechanism.

Diff Detail

Event Timeline

jeroen.dobbelaere requested review of this revision.Jun 29 2021, 7:17 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 29 2021, 7:17 AM
efriedma added inline comments.Jun 29 2021, 12:45 PM
llvm/lib/IR/Function.cpp
1670

Probably better not to assume the GlobalValue is a Function. Probably an invalid module if it isn't a function, but we might not check for that until later.

  • handle the case where the clashing GV is not a function.
jeroen.dobbelaere marked an inline comment as done.Jun 30 2021, 9:09 AM
apilipenko added inline comments.Jun 30 2021, 9:45 AM
llvm/lib/IR/Function.cpp
1667

I think it should be remangleIntrinsicFunction caller responsibility to do this kind of adjustment. Some of the callers (like LLParser) will just assert that the resulting function matches the signature. Others, like bitcode reader, will need to handle this situation.

llvm/lib/IR/Function.cpp
1667

Even in the LLParser use case, I think we can end up in a similar situation: a first rewrite could end up in a name clash with a function that is only rewritten later.

Added testcase showing a similar problem in LLParser that is also fixed by this patch.

apilipenko accepted this revision.Jul 1 2021, 8:59 AM

Looks good.

May I ask you to document the new side effect (possible renaming of another function in the Module) of remangleIntrinsicFunction in the corresponding header?

llvm/lib/IR/Function.cpp
1666–1681

Stylistic suggestions. This can be restructured to use a lambda and early exits. Something like this:

Function *NewDecl = [&] () {
  if (auto *ExistingGV = F->getParent()->getNamedValue(WantedName)) {
    if (auto *ExistingF = dyn_cast<Function>(ExistingGV))
      if (ExistingF->getFunctionType() == F->getFunctionType())
        return ExistingF;

    // The name already exists, but is not a function or has the wrong
    // prototype. Make place for the new one by renaming the old version.
    // Either this old version will be removed later on or the module is
    // invalid and we'll get an error.
    ExistingGV->setName(WantedName + ".renamed");
  }

  return Intrinsic::getDeclaration(F->getParent(), ID, ArgTys);
}();
This revision is now accepted and ready to land.Jul 1 2021, 8:59 AM

Rebased; Added comment about the side effect. Stylistic change as proposed by Artur.

jeroen.dobbelaere marked an inline comment as done.Jul 12 2021, 6:23 AM

Thanks for the review and the suggestions.

I'll do the actual commit tomorrow.

This revision was landed with ongoing or failed builds.Jul 13 2021, 2:40 AM
This revision was automatically updated to reflect the committed changes.

Thank you for this fix!