[LLVMdev] Problem with linking modules which use a shared type
Marcus Frenkel
marcus.frenkel at FernUni-Hagen.de
Thu Jun 27 03:44:09 PDT 2013
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
More information about the llvm-dev
mailing list