[LLVMdev] Fwd: error while linking modules with exception handling demo code
Duncan Sands
baldrick at free.fr
Sun Dec 16 07:21:20 PST 2012
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
>
More information about the llvm-dev
mailing list