1; The assertions in this file were autogenerated by 2; utils/update_llc_test_checks.py, but were hand-edited to add the 3; "end_function" lines to prevent the tests from passing when there are 4; superfluous instructions at the end of a function. You can run 5; update_llc_test_checks.py again, but please keep the "end_function" lines 6; intact when you commit. 7 8; Wasm, to generate valid code, always internally sets `--trap-unreachable` to 1 9; and `--no-trap-after-noreturn` to 0, and these command lines options, if 10; explicitly given, are ignored. Various combinations of these options should 11; have no effect and should not generate invalid code. 12; RUN: llc < %s -verify-machineinstrs | FileCheck %s 13; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s 14; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s 15; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs --trap-unreachable | FileCheck %s 16; RUN: llc < %s -verify-machineinstrs --trap-unreachable --no-trap-after-noreturn | FileCheck %s 17; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs --trap-unreachable --no-trap-after-noreturn | FileCheck %s 18 19target triple = "wasm32-unknown-unknown" 20 21 22; Test that the LLVM trap and debug trap intrinsics are lowered to wasm 23; unreachable. 24 25declare void @llvm.trap() cold noreturn nounwind 26declare void @llvm.debugtrap() nounwind 27 28define void @trap_ret_void() { 29; CHECK-LABEL: trap_ret_void: 30; CHECK: .functype trap_ret_void () -> () 31; CHECK-NEXT: # %bb.0: 32; CHECK-NEXT: unreachable 33; CHECK-NEXT: end_function 34 call void @llvm.trap() 35 ret void 36} 37 38define void @debugtrap_ret_void() { 39; CHECK-LABEL: debugtrap_ret_void: 40; CHECK: .functype debugtrap_ret_void () -> () 41; CHECK-NEXT: # %bb.0: 42; CHECK-NEXT: unreachable 43; CHECK-NEXT: # fallthrough-return 44; CHECK-NEXT: end_function 45 call void @llvm.debugtrap() 46 ret void 47} 48 49; LLVM trap followed by LLVM unreachable could become exactly one wasm 50; unreachable, but two are emitted currently. 51define void @trap_unreacheable() { 52; CHECK-LABEL: trap_unreacheable: 53; CHECK: .functype trap_unreacheable () -> () 54; CHECK-NEXT: # %bb.0: 55; CHECK-NEXT: unreachable 56; CHECK-NEXT: end_function 57 call void @llvm.trap() 58 unreachable 59} 60 61 62; Test that LLVM unreachable instruction is lowered to wasm unreachable when 63; necessary to fulfill the wasm operand stack requirements. 64 65declare void @ext_func() 66declare i32 @ext_func_i32() 67declare void @ext_never_return() noreturn 68 69; LLVM IR's 'unreachable' is translated to Wasm 'unreachable'. 70define i32 @missing_ret_unreachable() { 71; CHECK-LABEL: missing_ret_unreachable: 72; CHECK: .functype missing_ret_unreachable () -> (i32) 73; CHECK-NEXT: # %bb.0: 74; CHECK-NEXT: call ext_func 75; CHECK-NEXT: unreachable 76; CHECK-NEXT: end_function 77 call void @ext_func() 78 unreachable 79} 80 81; This is similar to the above test, but the callee has a 'noreturn' attribute. 82; There is an optimization that removes an 'unreachable' after a noreturn call, 83; but Wasm backend doesn't use it and ignore `--no-trap-after-noreturn`, if 84; given, to generate valid code. 85define i32 @missing_ret_noreturn_unreachable() { 86; CHECK-LABEL: missing_ret_noreturn_unreachable: 87; CHECK: .functype missing_ret_noreturn_unreachable () -> (i32) 88; CHECK-NEXT: # %bb.0: 89; CHECK-NEXT: call ext_never_return 90; CHECK-NEXT: unreachable 91; CHECK-NEXT: end_function 92 call void @ext_never_return() 93 unreachable 94} 95 96define i32 @no_crash_for_other_instruction_after_trap(ptr %p, i32 %b) { 97; CHECK-LABEL: no_crash_for_other_instruction_after_trap: 98; CHECK: unreachable 99; CHECK-NEXT: end_function 100 %a = load i32, ptr %p 101 call void @llvm.trap() 102 ret i32 %a 103} 104