[PATCH] D73208: [objc_direct] fix codegen for mismatched Decl/Impl return types

Duncan P. N. Exon Smith via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 30 12:58:01 PST 2020


dexonsmith added a comment.

In D73208#1837909 <https://reviews.llvm.org/D73208#1837909>, @MadCoder wrote:

> In D73208#1836789 <https://reviews.llvm.org/D73208#1836789>, @dexonsmith wrote:
>
> > I think we're talking across each other.  The idea is check the type when generating the implementation; if it's not correct, you fix it (need to update existing uses to bitcast).  So the type used for the implementation would match dynamic methods.
>
>
> ah I see, I don't know how to do that, I couldn't figure out how to fix the function declaration, if you want to give it a stab I'd love it.


I missed that question until now.  This uses `llvm::Value::replaceAllUsesWith`, if you `git grep` through clang you'll find examples.

Here's one from `CodeGenFunction::AddInitializerToStaticVarDecl`:

  // The initializer may differ in type from the global. Rewrite
  // the global to match the initializer.  (We have to do this
  // because some types, like unions, can't be completely represented
  // in the LLVM type system.)
  if (GV->getType()->getElementType() != Init->getType()) {
    llvm::GlobalVariable *OldGV = GV;
  
    GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
                                  OldGV->isConstant(),
                                  OldGV->getLinkage(), Init, "",
                                  /*InsertBefore*/ OldGV,
                                  OldGV->getThreadLocalMode(),
                           CGM.getContext().getTargetAddressSpace(D.getType()));
    GV->setVisibility(OldGV->getVisibility());
    GV->setDSOLocal(OldGV->isDSOLocal());
    GV->setComdat(OldGV->getComdat());
  
    // Steal the name of the old global
    GV->takeName(OldGV);
  
    // Replace all uses of the old global with the new global
    llvm::Constant *NewPtrForOldDecl =
    llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
    OldGV->replaceAllUsesWith(NewPtrForOldDecl);
  
    // Erase the old global, since it is no longer used.
    OldGV->eraseFromParent();
  }

This example is analogous to your case.  The pattern is:

1. Create the new thing (with no name, or with a temporary/bad name).
2. Steal the name of the old thing.
3. Bitcast from the new thing to the old type.
4. RAUW to replace all uses of the old thing with the bitcast-of-new-thing from (3).
5. Delete the old thing.

The RAUW isn't going to fix up the `DenseMap` you have on the side though, so you'll need to handle that explicitly; likely during step (4) makes sense.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73208/new/

https://reviews.llvm.org/D73208





More information about the cfe-commits mailing list