104 lines · plain
1; The assertions in this file were autogenerated by2; utils/update_llc_test_checks.py, but were hand-edited to add the3; "end_function" lines to prevent the tests from passing when there are4; superfluous instructions at the end of a function. You can run5; update_llc_test_checks.py again, but please keep the "end_function" lines6; intact when you commit.7 8; Wasm, to generate valid code, always internally sets `--trap-unreachable` to 19; and `--no-trap-after-noreturn` to 0, and these command lines options, if10; explicitly given, are ignored. Various combinations of these options should11; have no effect and should not generate invalid code.12; RUN: llc < %s -verify-machineinstrs | FileCheck %s13; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s14; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s15; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs --trap-unreachable | FileCheck %s16; RUN: llc < %s -verify-machineinstrs --trap-unreachable --no-trap-after-noreturn | FileCheck %s17; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs --trap-unreachable --no-trap-after-noreturn | FileCheck %s18 19target triple = "wasm32-unknown-unknown"20 21 22; Test that the LLVM trap and debug trap intrinsics are lowered to wasm23; unreachable.24 25declare void @llvm.trap() cold noreturn nounwind26declare void @llvm.debugtrap() nounwind27 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: unreachable33; CHECK-NEXT: end_function34 call void @llvm.trap()35 ret void36}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: unreachable43; CHECK-NEXT: # fallthrough-return44; CHECK-NEXT: end_function45 call void @llvm.debugtrap()46 ret void47}48 49; LLVM trap followed by LLVM unreachable could become exactly one wasm50; 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: unreachable56; CHECK-NEXT: end_function57 call void @llvm.trap()58 unreachable59}60 61 62; Test that LLVM unreachable instruction is lowered to wasm unreachable when63; necessary to fulfill the wasm operand stack requirements.64 65declare void @ext_func()66declare i32 @ext_func_i32()67declare void @ext_never_return() noreturn68 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_func75; CHECK-NEXT: unreachable76; CHECK-NEXT: end_function77 call void @ext_func()78 unreachable79}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`, if84; 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_return90; CHECK-NEXT: unreachable91; CHECK-NEXT: end_function92 call void @ext_never_return()93 unreachable94}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: unreachable99; CHECK-NEXT: end_function100 %a = load i32, ptr %p101 call void @llvm.trap()102 ret i32 %a103}104