Marcus Frenkel
2013-Jun-27 10:44 UTC
[LLVMdev] Problem with linking modules which use a shared type
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
Jeremy Lakeman
2013-Jun-28 02:35 UTC
[LLVMdev] Problem with linking modules which use a shared type
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> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130628/f39cc8f8/attachment.html>
Marcus Frenkel
2013-Jul-01 06:46 UTC
[LLVMdev] Problem with linking modules which use a shared type
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> >>