[LLVMdev] Linking modules across contexts crashes

Duncan P. N. Exon Smith dexonsmith at apple.com
Thu Jun 4 16:20:57 PDT 2015


> On 2015 Jun 4, at 14:58, Yuri <yuri at rawbw.com> wrote:
> 
> On 06/04/2015 14:29, Rafael EspĂ­ndola wrote:
>> Constants are unfortunately part of the Context, not the module
> 
> But types are also part of the Context, so I need to re-create these objects in another context.
> 
> GV.Op<0> = C->changeContext(NewContext); is supposed to replace the old context with the new one inside of the GlobalValue in Module.
> And same for types in many places.
> 
> The downside is that the older objects are left in the old context.
> 
> I actually went through the 80% of the changes, only such complex constants are left.
> 
> Yuri

I think the other option -- generating a clone of a Module in the
new context -- is probably easier, although I'm not sure.  Either way,
you'll need something like this:

    class Remapper {
      DenseMap<Type *, Type *> Types;
      DenseMap<Constant *, Constant *> Constants;
      DenseMap<Metadata *, Metadata *> MDs;
      DenseMap<unsigned, unsigned> AttachmentIDs;
      /* ... other things stored in the context ... */

      LLVMContext &NewContext;

    public:
      Type &remapType(Type &OldType);
      Constant &remapConstant(Constant &OldConstant);
      Metadata &remapMetadata(Metadata &OldMD);
      unsigned remapAttachmentID(unsigned OldAttachmentID);

      /// Map old global value to the new one.
      void mapGlobal(GlobalValue &OldGV, GlobalValue &NewGV);

      /* ... more API and internals ... */
    };

Where I'm assuming `remapType()` checks for `OldType` in the map, and
if it's not there generates the type in `NewContext` (and caches it in
the map).  Same deal with the other maps.

If you go with the "create a new module" approach, I think you
basically want to do the following:

 1. Create a new module, give it a name, etc.
 2. For each global value (for each global and function), create a
    dummy value, leaving the initializer unset.  You'll have to
    generate types on-demand as you go.  Register the new global
    values in the remapper.
 3. Fill in the initializers and function bodies, remapping Values/
    Constants/Metadata/Types as you go.
 4. Visit the named md nodes, remapping as you go.
 5. ...?

Note that I don't think this is a small project.  I suspect a fair
bit of code from the ValueMapper could/should be shared or refactored.

I think the "mutate the module" approach would have some interesting
corner cases that the "create a new module" approach doesn't, but it's
probably doable somehow, and I suspect needs roughly the same
algorithm.



More information about the llvm-dev mailing list