charles quarra
2012-Dec-13 16:57 UTC
[LLVMdev] Fwd: error while linking modules with exception handling demo code
---------- Forwarded message ---------- From: charles quarra <charllsnotieneningunputocorreo at gmail.com> Date: 2012/12/13 Subject: error while linking modules with exception handling demo code To: llvmdev at cs.uiuc.edu Hi, I am building a module X with an arithmetic function foo, a module Y with an arithmetic function foo2 that invokes foo. For the invocation be a proper one (being able to handle exceptions correctly) i incorporated a third module that has defined exception-handling code that i've taken from the ExceptionDemo sample. First i'll post the module dump, the failed assertion and then i'll explain a bit about how do i generate the code: this is the module ExecutableCodeModule dump, which is the module that is used by the ExecutionEngine (not using new MCJIT, but it is not relevant for this question, since the error happens during linkage). It contains definitions from the ExceptionDemo sample AND the foo function of module X already linked (modules are being linked with linker()->LinkModules(ExecutableCodeModule , moduleToLink, llvm::Linker::PreserveSource, &errorMsg); Exception Demo is from https://llvm.org/svn/llvm-project/llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp ; ModuleID = 'ExecutableCodeModule' @typeInfo0 = constant { i32 } zeroinitializer @typeInfo1 = constant { i32 } { i32 1 } @typeInfo2 = constant { i32 } { i32 2 } @typeInfo3 = constant { i32 } { i32 3 } @typeInfo4 = constant { i32 } { i32 4 } @typeInfo5 = constant { i32 } { i32 5 } @typeInfo6 = constant { i32 } { i32 6 } declare void @print32Int(i32, i8*) declare void @print64Int(i64, i8*) declare void @printStr(i8*) declare void @throwCppException(i32) declare void @deleteOurException(i8*) declare i8* @createOurException(i32) declare i32 @_Unwind_RaiseException(i8*) noreturn declare i32 @_Unwind_Resume(i8*) noreturn declare i32 @ourPersonality(i32, i32, i64, i8*, i8*) declare i32 @llvm.eh.typeid.for(i8*) nounwind readnone define i32 @foo(i32) { %g = alloca i32 %bar = alloca i32 store i32 %0, i32* %bar %"argument read" = load i32* %bar %addtmp = add i32 %"argument read", 2 store i32 %addtmp, i32* %g %"argument read1" = load i32* %bar %read = load i32* %g %"Code::Op::Mul" = mul i32 %"argument read1", %read ret i32 %"Code::Op::Mul" } this is module Y, which is where foo2 is generated. When it is supposed to invoke foo, i've placed createCatchWrappedInvokeFunction(*module, *excptModule, buildParameters.builder, *buildParameters.getFunctionPassManager(), *result, //result is llvm::Function pointing to foo in module X "invoke foo", numExceptionTypesToCatch, innerExceptionTypesToCatch); (at the end i put the code for createCatchWrappedInvokeFunction, which is slightly modified to allow for things like printStr and createOurException that exists in the separate exception handling module to be used in the module Y) ; ModuleID = 'Y' @0 = linker_private constant [52 x i8] c"Gen: Executing finally block finally in invoke foo\0A\00" @1 = linker_private constant [52 x i8] c"Gen: Executing catch block typeInfo6 in invoke foo\0A\00" @2 = linker_private constant [52 x i8] c"Gen: Executing catch block typeInfo2 in invoke foo\0A\00" @3 = linker_private constant [52 x i8] c"Gen: Executing catch block typeInfo4 in invoke foo\0A\00" @4 = linker_private constant [43 x i8] c"Gen: In end block: exiting in invoke foo.\0A\00" @5 = linker_private constant [34 x i8] c"Gen: No exception in invoke foo!\0A\00" @6 = linker_private constant [34 x i8] c"Gen: Foreign exception received.\0A\00" @7 = linker_private constant [67 x i8] c"Gen: Exception type <%d> received (stack unwound) in invoke foo.\0A\00" define i32 @foo2(i32) { %h = alloca i32 %g = alloca i32 %bar = alloca i32 store i32 %0, i32* %bar %"argument read" = load i32* %bar %"Code::Op::Mul" = mul i32 %"argument read", 5 store i32 %"Code::Op::Mul", i32* %g %read = load i32* %g } define void @"invoke foo"(i32 %exceptTypeToThrow) { entry: %caughtResultStorage = alloca { i8*, i32 } store { i8*, i32 } zeroinitializer, { i8*, i32 }* %caughtResultStorage %exceptionStorage = alloca i8* store i8* null, i8** %exceptionStorage %exceptionCaught = alloca i8 store i8 0, i8* %exceptionCaught %0 = invoke i32 @foo(i32 %exceptTypeToThrow) to label %normal unwind label %exception normal: ; preds = %entry call void @printStr(i8* getelementptr inbounds ([34 x i8]* @5, i32 0, i32 0)) br label %finally exception: ; preds = %entry %1 = landingpad { i8*, i32 } personality i32 (i32, i32, i64, i8*, i8*)* @ourPersonality cleanup catch { i32 }* @typeInfo6 catch { i32 }* @typeInfo2 catch { i32 }* @typeInfo4 %2 = extractvalue { i8*, i32 } %1, 0 %3 = extractvalue { i8*, i32 } %1, 1 store { i8*, i32 } %1, { i8*, i32 }* %caughtResultStorage store i8* %2, i8** %exceptionStorage store i8 1, i8* %exceptionCaught %4 = bitcast i8* %2 to { i64 }* %5 = getelementptr inbounds { i64 }* %4, i32 0, i32 0 %6 = load i64* %5 %7 = icmp eq i64 %6, 8026094035810743040 br i1 %7, label %exceptionRoute, label %externalException exceptionRoute: ; preds = %exception %8 = getelementptr i8* %2, i64 4294967280 %9 = bitcast i8* %8 to { { i32 } }* %10 = getelementptr inbounds { { i32 } }* %9, i32 0, i32 0 %11 = getelementptr inbounds { i32 }* %10, i32 0, i32 0 %12 = load i32* %11 call void @print32Int(i32 %12, i8* getelementptr inbounds ([67 x i8]* @7, i32 0, i32 0)) switch i32 %3, label %finally [ i32 1, label %typeInfo6 i32 2, label %typeInfo2 i32 3, label %typeInfo4 ] store i32 %0, i32* %h %"argument read" = load i32* %bar %read = load i32* %h %addtmp = add i32 %"argument read", %read ret i32 %addtmp externalException: ; preds = %exception call void @printStr(i8* getelementptr inbounds ([34 x i8]* @6, i32 0, i32 0)) br label %finally unwindResume: ; preds = %finally %13 = load { i8*, i32 }* %caughtResultStorage resume { i8*, i32 } %13 end: ; preds = %finally, %finally call void @printStr(i8* getelementptr inbounds ([43 x i8]* @4, i32 0, i32 0)) %14 = load i8** %exceptionStorage call void @deleteOurException(i8* %14) ret void finally: ; preds %exceptionRoute, %externalException, %normal, %typeInfo4, %typeInfo2, %typeInfo6 call void @printStr(i8* getelementptr inbounds ([52 x i8]* @0, i32 0, i32 0)) %15 = load i8* %exceptionCaught switch i8 %15, label %end [ i8 2, label %end i8 1, label %unwindResume ] typeInfo6: ; preds = %exceptionRoute call void @printStr(i8* getelementptr inbounds ([52 x i8]* @1, i32 0, i32 0)) store i8 2, i8* %exceptionCaught br label %finally typeInfo2: ; preds = %exceptionRoute call void @printStr(i8* getelementptr inbounds ([52 x i8]* @2, i32 0, i32 0)) store i8 2, i8* %exceptionCaught br label %finally typeInfo4: ; preds = %exceptionRoute call void @printStr(i8* getelementptr inbounds ([52 x i8]* @3, i32 0, i32 0)) store i8 2, i8* %exceptionCaught br label %finally } this is the failed assertion i get during the call to Linker::LinkModules While deleting: i32 (i32)* %foo Use still stuck around after Def is destroyed: %0 = invoke i32 @foo(i32 %exceptTypeToThrow) to label %normal unwind label %exception hivecompilerlibtests: Value.cpp:75: virtual llvm::Value::~Value(): Assertion `use_empty() && "Uses remain when a value is destroyed!"' failed. As a separate but probably related detail, the function 'invoke foo' is not being inserted in the foo2 IR. The foo2 invoke generation looks like this: llvm::Module* module Compiler::Services::SymbolResolver::getInstance()->resolveOrCreateModule( buildParameters.getLLVMContext() , buildParameters.getModuleDefinition() ); HAssertMsg( 0 != module , " null module "); llvm::Module* excptModule Compiler::Services::SymbolResolver::getInstance()->resolveOrCreateNativeExceptionHandlingModule( buildParameters.getLLVMContext() ); //, buildParameters.getModuleDefinition() ); HAssertMsg( 0 != excptModule , " null exception module "); HDebugLogLevel("inside BuildIRExpression:, " << dynSym.getSymbolName() << " module resolved? " << excptModule, 0); Exceptions::InvokeFunctionResult invokeResult = Exceptions::createCatchWrappedInvokeFunction(*module, *excptModule, buildParameters.builder, *buildParameters.getFunctionPassManager(), *result, std::string("invoke ")+ fnDecl->functionName.get(), numExceptionTypesToCatch, innerExceptionTypesToCatch); the exceptionModule is being generated as: Compiler::Detail::Exceptions::initialiseExceptionHandlingStaticStuff(ctx); llvm::Module* excptModule = new llvm::Module("NativeExceptionHandlingModule" , ctx);Compiler::Detail::Exceptions::createStandardUtilityFunctions(6, * excptModule); my slightly modified version of ExceptionDemo is appended as an attachment -------------- next part -------------- A non-text attachment was scrubbed... Name: ExceptionHandling.tar.bz2 Type: application/x-bzip2 Size: 5450 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121213/704edf0c/attachment.bin>
Duncan Sands
2012-Dec-16 15:21 UTC
[LLVMdev] Fwd: error while linking modules with exception handling demo code
Hi Charles, can you reduce to two .ll files that cause llvm-link to assert? Ciao, Duncan. On 13/12/12 17:57, charles quarra wrote:> ---------- Forwarded message ---------- > From: charles quarra <charllsnotieneningunputocorreo at gmail.com> > Date: 2012/12/13 > Subject: error while linking modules with exception handling demo code > To: llvmdev at cs.uiuc.edu > > > Hi, > > > I am building a module X with an arithmetic function foo, a module Y > with an arithmetic function foo2 that invokes foo. For the invocation > be a proper one (being able to handle exceptions correctly) i > incorporated a third module that has defined exception-handling code > that i've taken from the ExceptionDemo sample. First i'll post the > module dump, the failed assertion and then i'll explain a bit about > how do i generate the code: > > this is the module ExecutableCodeModule dump, which is the module that > is used by the ExecutionEngine (not using new MCJIT, but it is not > relevant for this question, since the error happens during linkage). > It contains definitions from the ExceptionDemo sample AND the foo > function of module X already linked > > (modules are being linked with > linker()->LinkModules(ExecutableCodeModule , moduleToLink, > llvm::Linker::PreserveSource, &errorMsg); > > Exception Demo is from > https://llvm.org/svn/llvm-project/llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp > > ; ModuleID = 'ExecutableCodeModule' > > @typeInfo0 = constant { i32 } zeroinitializer > @typeInfo1 = constant { i32 } { i32 1 } > @typeInfo2 = constant { i32 } { i32 2 } > @typeInfo3 = constant { i32 } { i32 3 } > @typeInfo4 = constant { i32 } { i32 4 } > @typeInfo5 = constant { i32 } { i32 5 } > @typeInfo6 = constant { i32 } { i32 6 } > > declare void @print32Int(i32, i8*) > > declare void @print64Int(i64, i8*) > > declare void @printStr(i8*) > > declare void @throwCppException(i32) > > declare void @deleteOurException(i8*) > > declare i8* @createOurException(i32) > > declare i32 @_Unwind_RaiseException(i8*) noreturn > > declare i32 @_Unwind_Resume(i8*) noreturn > > declare i32 @ourPersonality(i32, i32, i64, i8*, i8*) > > declare i32 @llvm.eh.typeid.for(i8*) nounwind readnone > > define i32 @foo(i32) { > %g = alloca i32 > %bar = alloca i32 > store i32 %0, i32* %bar > %"argument read" = load i32* %bar > %addtmp = add i32 %"argument read", 2 > store i32 %addtmp, i32* %g > %"argument read1" = load i32* %bar > %read = load i32* %g > %"Code::Op::Mul" = mul i32 %"argument read1", %read > ret i32 %"Code::Op::Mul" > } > > this is module Y, which is where foo2 is generated. When it is > supposed to invoke foo, i've placed > createCatchWrappedInvokeFunction(*module, *excptModule, > buildParameters.builder, > > *buildParameters.getFunctionPassManager(), > *result, //result > is llvm::Function pointing to foo in module X > "invoke foo", > numExceptionTypesToCatch, > innerExceptionTypesToCatch); > > (at the end i put the code for createCatchWrappedInvokeFunction, which > is slightly modified to allow for things like printStr and > createOurException that exists in the separate exception handling > module to be used in the module Y) > > ; ModuleID = 'Y' > > @0 = linker_private constant [52 x i8] c"Gen: Executing finally block > finally in invoke foo\0A\00" > @1 = linker_private constant [52 x i8] c"Gen: Executing catch block > typeInfo6 in invoke foo\0A\00" > @2 = linker_private constant [52 x i8] c"Gen: Executing catch block > typeInfo2 in invoke foo\0A\00" > @3 = linker_private constant [52 x i8] c"Gen: Executing catch block > typeInfo4 in invoke foo\0A\00" > @4 = linker_private constant [43 x i8] c"Gen: In end block: exiting in > invoke foo.\0A\00" > @5 = linker_private constant [34 x i8] c"Gen: No exception in invoke foo!\0A\00" > @6 = linker_private constant [34 x i8] c"Gen: Foreign exception received.\0A\00" > @7 = linker_private constant [67 x i8] c"Gen: Exception type <%d> > received (stack unwound) in invoke foo.\0A\00" > > define i32 @foo2(i32) { > %h = alloca i32 > %g = alloca i32 > %bar = alloca i32 > store i32 %0, i32* %bar > %"argument read" = load i32* %bar > %"Code::Op::Mul" = mul i32 %"argument read", 5 > store i32 %"Code::Op::Mul", i32* %g > %read = load i32* %g > } > > define void @"invoke foo"(i32 %exceptTypeToThrow) { > entry: > %caughtResultStorage = alloca { i8*, i32 } > store { i8*, i32 } zeroinitializer, { i8*, i32 }* %caughtResultStorage > %exceptionStorage = alloca i8* > store i8* null, i8** %exceptionStorage > %exceptionCaught = alloca i8 > store i8 0, i8* %exceptionCaught > %0 = invoke i32 @foo(i32 %exceptTypeToThrow) > to label %normal unwind label %exception > > normal: ; preds = %entry > call void @printStr(i8* getelementptr inbounds ([34 x i8]* @5, i32 0, i32 0)) > br label %finally > > exception: ; preds = %entry > %1 = landingpad { i8*, i32 } personality i32 (i32, i32, i64, i8*, > i8*)* @ourPersonality > cleanup > catch { i32 }* @typeInfo6 > catch { i32 }* @typeInfo2 > catch { i32 }* @typeInfo4 > %2 = extractvalue { i8*, i32 } %1, 0 > %3 = extractvalue { i8*, i32 } %1, 1 > store { i8*, i32 } %1, { i8*, i32 }* %caughtResultStorage > store i8* %2, i8** %exceptionStorage > store i8 1, i8* %exceptionCaught > %4 = bitcast i8* %2 to { i64 }* > %5 = getelementptr inbounds { i64 }* %4, i32 0, i32 0 > %6 = load i64* %5 > %7 = icmp eq i64 %6, 8026094035810743040 > br i1 %7, label %exceptionRoute, label %externalException > > exceptionRoute: ; preds = %exception > %8 = getelementptr i8* %2, i64 4294967280 > %9 = bitcast i8* %8 to { { i32 } }* > %10 = getelementptr inbounds { { i32 } }* %9, i32 0, i32 0 > %11 = getelementptr inbounds { i32 }* %10, i32 0, i32 0 > %12 = load i32* %11 > call void @print32Int(i32 %12, i8* getelementptr inbounds ([67 x > i8]* @7, i32 0, i32 0)) > switch i32 %3, label %finally [ > i32 1, label %typeInfo6 > i32 2, label %typeInfo2 > i32 3, label %typeInfo4 > ] > store i32 %0, i32* %h > %"argument read" = load i32* %bar > %read = load i32* %h > %addtmp = add i32 %"argument read", %read > ret i32 %addtmp > > externalException: ; preds = %exception > call void @printStr(i8* getelementptr inbounds ([34 x i8]* @6, i32 0, i32 0)) > br label %finally > > unwindResume: ; preds = %finally > %13 = load { i8*, i32 }* %caughtResultStorage > resume { i8*, i32 } %13 > > end: ; preds = %finally, %finally > call void @printStr(i8* getelementptr inbounds ([43 x i8]* @4, i32 0, i32 0)) > %14 = load i8** %exceptionStorage > call void @deleteOurException(i8* %14) > ret void > > finally: ; preds > %exceptionRoute, %externalException, %normal, %typeInfo4, %typeInfo2, > %typeInfo6 > call void @printStr(i8* getelementptr inbounds ([52 x i8]* @0, i32 0, i32 0)) > %15 = load i8* %exceptionCaught > switch i8 %15, label %end [ > i8 2, label %end > i8 1, label %unwindResume > ] > > typeInfo6: ; preds = %exceptionRoute > call void @printStr(i8* getelementptr inbounds ([52 x i8]* @1, i32 0, i32 0)) > store i8 2, i8* %exceptionCaught > br label %finally > > typeInfo2: ; preds = %exceptionRoute > call void @printStr(i8* getelementptr inbounds ([52 x i8]* @2, i32 0, i32 0)) > store i8 2, i8* %exceptionCaught > br label %finally > > typeInfo4: ; preds = %exceptionRoute > call void @printStr(i8* getelementptr inbounds ([52 x i8]* @3, i32 0, i32 0)) > store i8 2, i8* %exceptionCaught > br label %finally > } > > this is the failed assertion i get during the call to Linker::LinkModules > > > While deleting: i32 (i32)* %foo > Use still stuck around after Def is destroyed: %0 = invoke i32 > @foo(i32 %exceptTypeToThrow) > to label %normal unwind label %exception > hivecompilerlibtests: Value.cpp:75: virtual llvm::Value::~Value(): > Assertion `use_empty() && "Uses remain when a value is destroyed!"' > failed. > > > As a separate but probably related detail, the function 'invoke foo' > is not being inserted in the foo2 IR. The foo2 invoke generation looks > like this: > > llvm::Module* module > Compiler::Services::SymbolResolver::getInstance()->resolveOrCreateModule( > buildParameters.getLLVMContext() , > buildParameters.getModuleDefinition() ); > HAssertMsg( 0 != module , " null module "); > llvm::Module* excptModule > Compiler::Services::SymbolResolver::getInstance()->resolveOrCreateNativeExceptionHandlingModule( > buildParameters.getLLVMContext() ); //, > buildParameters.getModuleDefinition() ); > HAssertMsg( 0 != excptModule , " null > exception module "); > HDebugLogLevel("inside BuildIRExpression:, " > << dynSym.getSymbolName() << " module resolved? " << excptModule, 0); > Exceptions::InvokeFunctionResult invokeResult > = Exceptions::createCatchWrappedInvokeFunction(*module, *excptModule, > buildParameters.builder, > > *buildParameters.getFunctionPassManager(), > *result, > > std::string("invoke ")+ fnDecl->functionName.get(), > numExceptionTypesToCatch, > innerExceptionTypesToCatch); > > the exceptionModule is being generated as: > > Compiler::Detail::Exceptions::initialiseExceptionHandlingStaticStuff(ctx); > llvm::Module* excptModule = new > llvm::Module("NativeExceptionHandlingModule" , > ctx);Compiler::Detail::Exceptions::createStandardUtilityFunctions(6, * > excptModule); > > > my slightly modified version of ExceptionDemo is appended as an attachment > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >
Rafael EspĂndola
2012-Dec-18 15:42 UTC
[LLVMdev] Fwd: error while linking modules with exception handling demo code
> define i32 @foo2(i32) { > %h = alloca i32 > %g = alloca i32 > %bar = alloca i32 > store i32 %0, i32* %bar > %"argument read" = load i32* %bar > %"Code::Op::Mul" = mul i32 %"argument read", 5 > store i32 %"Code::Op::Mul", i32* %g > %read = load i32* %g > } >I tried to reproduce the assert, but llvm-link fails to parse this as it is a missing a return. Cheers, Rafael