79 lines · plain
1; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s2 3; WinEH requires funclet tokens on nounwind intrinsics if they can lower to4; regular function calls in the course of IR transformations.5;6; Test that the code generator will emit the function call and not consider it7; an "implausible instruciton". In the past this silently truncated code on8; exception paths and caused crashes at runtime.9;10; Reduced IR generated from ObjC++ source:11;12; @class Ety;13; void opaque(void);14; void test_catch_with_objc_intrinsic(void) {15; @try {16; opaque();17; } @catch (Ety *ex) {18; // Destroy ex when leaving catchpad. This would emit calls to two19; // intrinsic functions: llvm.objc.retain and llvm.objc.storeStrong20; }21; }22;23; llvm.objc.retain and llvm.objc.storeStrong both lower into regular function24; calls before ISel. We only need one of them to trigger funclet truncation25; during codegen:26 27define void @test_catch_with_objc_intrinsic() personality ptr @__CxxFrameHandler3 {28entry:29 %exn.slot = alloca ptr, align 830 %ex2 = alloca ptr, align 831 invoke void @opaque() to label %invoke.cont unwind label %catch.dispatch32 33catch.dispatch: ; preds = %entry34 %0 = catchswitch within none [label %catch] unwind to caller35 36invoke.cont: ; preds = %entry37 unreachable38 39catch: ; preds = %catch.dispatch40 %1 = catchpad within %0 [ptr null, i32 64, ptr %exn.slot]41 %exn = load ptr, ptr %exn.slot, align 842 %2 = call ptr @llvm.objc.retain(ptr %exn) [ "funclet"(token %1) ]43 store ptr %2, ptr %ex2, align 844 catchret from %1 to label %catchret.dest45 46catchret.dest: ; preds = %catch47 ret void48}49 50declare void @opaque()51declare ptr @llvm.objc.retain(ptr) #052declare i32 @__CxxFrameHandler3(...)53 54attributes #0 = { nounwind }55 56; EH catchpad with SEH prologue:57; CHECK-LABEL: # %catch58; CHECK: pushq %rbp59; CHECK: .seh_pushreg %rbp60; ...61; CHECK: .seh_endprologue62;63; At this point the code used to be truncated (and sometimes terminated with an64; int3 opcode):65; CHECK-NOT: int366;67; Instead, the runtime call to retain should be emitted:68; CHECK: movq -8(%rbp), %rcx69; CHECK: callq objc_retain70; ...71;72; This is the end of the funclet:73; CHECK: popq %rbp74; CHECK: retq # CATCHRET75; ...76; CHECK: .seh_handlerdata77; ...78; CHECK: .seh_endproc79