Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/MachineFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
// RegInfo - Information about each register in use in the function.
MachineRegisterInfo *RegInfo;

// Used to keep track of target-specific per-machine function information for
// Used to keep track of target-specific per-machine-function information for
// the target implementation.
MachineFunctionInfo *MFInfo;

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/MachineInstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1276,7 +1276,7 @@ class MachineInstr
/// eraseFromBundle() to erase individual bundled instructions.
void eraseFromParent();

/// Unlink 'this' form its basic block and delete it.
/// Unlink 'this' from its basic block and delete it.
///
/// If the instruction is part of a bundle, the other instructions in the
/// bundle remain bundled.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {

// When there is an unconditional branch right before a catch instruction and
// it branches to the end of end_try marker, we don't need the branch, because
// it there is no exception, the control flow transfers to that point anyway.
// if there is no exception, the control flow transfers to that point anyway.
// bb0:
// try
// ...
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
// LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
// 'unreachable' instructions which is meant for that case.
this->Options.TrapUnreachable = true;
this->Options.NoTrapAfterNoreturn = false;

// WebAssembly treats each function as an independent unit. Force
// -ffunction-sections, effectively, so that we can emit them independently.
Expand Down
102 changes: 82 additions & 20 deletions llvm/test/CodeGen/WebAssembly/unreachable.ll
Original file line number Diff line number Diff line change
@@ -1,33 +1,95 @@
; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s
; The assertions in this file were autogenerated by
; utils/update_llc_test_checks.py, but were hand-edited to add the
; "end_function" lines to prevent the tests from passing when there
; are superfluous instructions at the end of a function.
; You can run update_llc_test_checks.py again, but please keep the
; "end_function" lines intact when you commit.

; Test that LLVM unreachable instruction and trap intrinsic are lowered to
; wasm unreachable

; The --trap-unreachable and --no-trap-after-noreturn options are ignored, and
; should have no effect.
; RUN: llc < %s -verify-machineinstrs | FileCheck %s
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s
; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs --trap-unreachable | FileCheck %s
; RUN: llc < %s -verify-machineinstrs --trap-unreachable --no-trap-after-noreturn | FileCheck %s
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs --trap-unreachable --no-trap-after-noreturn | FileCheck %s

target triple = "wasm32-unknown-unknown"

declare void @llvm.trap()
declare void @llvm.debugtrap()
declare void @abort()

; CHECK-LABEL: f1:
; CHECK: call abort{{$}}
; CHECK: unreachable
define i32 @f1() {
call void @abort()
unreachable
}
; Test that the LLVM trap and debug trap intrinsics are lowered to wasm
; unreachable.

declare void @llvm.trap() cold noreturn nounwind
declare void @llvm.debugtrap() nounwind

; CHECK-LABEL: f2:
; CHECK: unreachable
define void @f2() {
define void @trap_ret_void() {
; CHECK-LABEL: trap_ret_void:
; CHECK: .functype trap_ret_void () -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: unreachable
; CHECK-NEXT: # fallthrough-return
; CHECK-NEXT: end_function
call void @llvm.trap()
ret void
}

; CHECK-LABEL: f3:
; CHECK: unreachable
define void @f3() {
define void @debugtrap_ret_void() {
; CHECK-LABEL: debugtrap_ret_void:
; CHECK: .functype debugtrap_ret_void () -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: unreachable
; CHECK-NEXT: # fallthrough-return
; CHECK-NEXT: end_function
call void @llvm.debugtrap()
ret void
}

; LLVM trap followed by LLVM unreachable could become exactly one wasm
; unreachable, but two are emitted currently.
define void @trap_unreacheable() {
; CHECK-LABEL: trap_unreacheable:
; CHECK: .functype trap_unreacheable () -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: unreachable
; CHECK-NEXT: unreachable
; CHECK-NEXT: end_function
call void @llvm.trap()
unreachable
}


; Test that LLVM unreachable instruction is lowered to wasm unreachable when
; necessary to fulfill the wasm operand stack requirements.

declare void @ext_func()
declare i32 @ext_func_i32()
declare void @ext_never_return() noreturn

; The wasm unreachable in this test is necessary for the function to pass wasm
; validation.
define i32 @missing_ret_unreachable() {
; CHECK-LABEL: missing_ret_unreachable:
; CHECK: .functype missing_ret_unreachable () -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: call ext_func
; CHECK-NEXT: unreachable
; CHECK-NEXT: end_function
call void @ext_func()
unreachable
}

; This is similar to the above test, but ensures wasm unreachable is emitted
; even after a noreturn call. Using --no-trap-after-noreturn was previously
; known to break this.
define i32 @missing_ret_noreturn_unreachable() {
; CHECK-LABEL: missing_ret_noreturn_unreachable:
; CHECK: .functype missing_ret_noreturn_unreachable () -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: call ext_never_return
; CHECK-NEXT: unreachable
; CHECK-NEXT: end_function
call void @ext_never_return()
unreachable
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No newline at the end