[LLVMdev] Problem with linking modules which use a shared type

Marcus Frenkel marcus.frenkel at FernUni-Hagen.de
Sun Jun 30 23:46:06 PDT 2013


I tried that also, but got some errors out of it, probably due to running the interpreter directly on the module instead of just generating bytecode from it. So there is currently no proper way to avoid the problem at all?


Am 28.06.2013, 04:35 Uhr, schrieb Jeremy Lakeman <Jeremy.Lakeman at gmail.com>:

> I've tripped over this behaviour as well. I ended up working around the
> problem by creating a new context every time I wanted to link modules
> together. Which led to me accidently generating one module using two
> different contexts. Which isn't an error that is detected by module
> verification. It only causes issues for comparisons like Type equality that
> compare pointers, and those types of problems can be tricky to debug.
>
>
> On Thu, Jun 27, 2013 at 8:14 PM, Marcus Frenkel <
> marcus.frenkel at fernuni-hagen.de> wrote:
>
>> Hi,
>>
>> I stumbled upon a strange thing regarding types and module linking, which
>> I don't quite get, so maybe someone around here can enlighten me.
>>
>> Consider the following code, which will create 2 modules m1 and m2, and a
>> named structured type %T = { i32 }; m1 contains only a function definition
>> f(%T), m2 contains a function declaration f(%T) and a function definition
>> h(%T), where h will call f in its body. Note that all functions in m1 and
>> m2 are based upon the same structured type %T:
>>
>>     LLVMContext context;
>>     BasicBlock* b;
>>
>>     // modules
>>     Module *m1 = new Module( "m1", context ),
>>            *m2 = new Module( "m2", context );
>>
>>     // types
>>     vector<Type*> types;
>>
>>     types.push_back( IntegerType::get( context, 32 ) );
>>
>>     Type* sType = StructType::create( types, "T" );
>>
>>     types.clear();
>>     types.push_back( sType );
>>
>>     FunctionType* ft = FunctionType::get( Type::getVoidTy( context ),
>> types, false );
>>
>>     // m1
>>     Function* f = Function::Create( ft, GlobalValue::ExternalLinkage, "f",
>> m1 );
>>
>>     b = BasicBlock::Create( context, "b", f );
>>     ReturnInst::Create( context, b );
>>
>>     verifyModule(*m1);
>>
>>     // m2
>>     Function* fDecl = Function::Create( ft, GlobalValue::ExternalLinkage,
>> "f", m2 );
>>     Function* h = Function::Create( ft, GlobalValue::ExternalLinkage, "h",
>> m2 );
>>
>>     vector<Value*> args;
>>     args.push_back( h->arg_begin() );
>>
>>     b = BasicBlock::Create( context, "b", h );
>>     CallInst::Create( fDecl, args, "", b );
>>     ReturnInst::Create( context, b );
>>
>>     verifyModule(*m2);
>>
>>
>> Each module for itself is okay and passes the verification, leading to the
>> following IR code:
>>
>>     ; ModuleID = 'm1'
>>
>>     %T = type { i32 }
>>
>>     define void @f(%T) {
>>     b:
>>       ret void
>>     }
>>
>>     =====================
>>     ; ModuleID = 'm2'
>>
>>     %T = type { i32 }
>>
>>     declare void @f(%T)
>>
>>     define void @h(%T) {
>>     b:
>>       call void @f(%T %0)
>>       ret void
>>     }
>>
>>
>> However, if both modules are linked together as per
>>
>>     // link
>>     Linker::LinkModules( m1, m2, Linker::DestroySource, nullptr );
>>     verifyModule(*m1);
>>
>>
>> the type %T in both modules will not be unified, but instead two separate
>> types %T and %0 will be introduced, leading to the following IR code, which
>> of course won't pass the verification any more due to type
>> incompatibilities in the function call:
>>
>>     ; ModuleID = 'm1'
>>
>>     %0 = type { i32 }
>>     %T = type { i32 }
>>
>>     define void @f(%0) {
>>     b:
>>       ret void
>>     }
>>
>>     define void @h(%T) {
>>     b:
>>       call void @f(%T %0)
>>       ret void
>>     }
>>
>>
>> Even more strange, if both modules and the types are created separately
>> from each other (meaning, that the type %T is created for both modules
>> anew), but within the same LLVMContext, the call to LinkModules will result
>> in a proper module with a unified type %T.
>>
>> Is that a bug or a feature of LLVM? I thought that types will be handled
>> at context level and not module level, so that it should be clear that %T
>> in both m1 and m2 can be unified, given that they even are based upon the
>> same llvm::Type type (which becomes even more strange with the fact, that
>> they will be unified, when they are *not* based upon the same llvm::Type
>> type).
>>
>> Any explanation of that behavior would be much appreciated!
>>
>>
>> Cheers,
>> Marcus
>> ______________________________**_________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/**mailman/listinfo/llvmdev<http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev>
>>



More information about the llvm-dev mailing list