llvm/llvm/test/MC/WebAssembly/eh-assembly.s

# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+exception-handling --no-type-check < %s | FileCheck %s
# Check that it converts to .o without errors, but don't check any output:
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+exception-handling --no-type-check -o %t.o < %s

  .tagtype  __cpp_exception i32
  .tagtype  __c_longjmp i32
  .functype  foo () -> ()

eh_test:
  .functype  eh_test () -> ()

  # try_table with all four kinds of catch clauses
  block exnref
    block
      block () -> (i32, exnref)
        block i32
          try_table (catch __cpp_exception 0) (catch_ref __c_longjmp 1) (catch_all 2) (catch_all_ref 3)
            i32.const 0
            throw     __cpp_exception
          end_try_table
          return
        end_block
        drop
        return
      end_block
      throw_ref
      drop
    end_block
    return
  end_block
  drop

  # You can use the same kind of catch clause more than once
  block
    block exnref
      block
        try_table (catch_all 0) (catch_all_ref 1) (catch_all 2)
          call  foo
        end_try_table
      end_block
      return
    end_block
    drop
  end_block

  # Two catch clauses targeting the same block
  block
    try_table (catch_all 0) (catch_all 0)
    end_try_table
  end_block

  # try_table with a return type
  block
    try_table f32 (catch_all 0)
      f32.const 0.0
    end_try_table
    drop
  end_block

  # try_table with a multivalue type return
  block
    try_table () -> (i32, f32) (catch_all 0)
      i32.const 0
      f32.const 0.0
    end_try_table
    drop
    drop
  end_block

  # catch-less try_tables
  try_table
    call  foo
  end_try_table

  try_table i32
    i32.const 0
  end_try_table
  drop

  try_table () -> (i32, f32)
    i32.const 0
    f32.const 0.0
  end_try_table
  drop
  drop

  end_function

# CHECK-LABEL: eh_test:
# CHECK:         block           exnref
# CHECK-NEXT:    block
# CHECK-NEXT:    block           () -> (i32, exnref)
# CHECK-NEXT:    block           i32
# CHECK-NEXT:    try_table        (catch __cpp_exception 0) (catch_ref __c_longjmp 1) (catch_all 2) (catch_all_ref 3)
# CHECK:         i32.const       0
# CHECK-NEXT:    throw           __cpp_exception
# CHECK-NEXT:    end_try_table
# CHECK-NEXT:    return
# CHECK-NEXT:    end_block
# CHECK-NEXT:    drop
# CHECK-NEXT:    return
# CHECK-NEXT:    end_block
# CHECK-NEXT:    throw_ref
# CHECK-NEXT:    drop
# CHECK-NEXT:    end_block
# CHECK-NEXT:    return
# CHECK-NEXT:    end_block
# CHECK-NEXT:    drop

# CHECK:         block
# CHECK-NEXT:    block           exnref
# CHECK-NEXT:    block
# CHECK-NEXT:    try_table        (catch_all 0) (catch_all_ref 1) (catch_all 2)
# CHECK:         call    foo
# CHECK-NEXT:    end_try_table
# CHECK-NEXT:    end_block
# CHECK-NEXT:    return
# CHECK-NEXT:    end_block
# CHECK-NEXT:    drop
# CHECK-NEXT:    end_block

# CHECK:         block
# CHECK-NEXT:    try_table        (catch_all 0) (catch_all 0)
# CHECK:         end_try_table
# CHECK-NEXT:    end_block

# CHECK:         block
# CHECK-NEXT:    try_table       f32 (catch_all 0)
# CHECK:         f32.const       0x0p0
# CHECK-NEXT:    end_try_table
# CHECK-NEXT:    drop
# CHECK-NEXT:    end_block

# CHECK:         block
# CHECK-NEXT:    try_table       () -> (i32, f32) (catch_all 0)
# CHECK:         i32.const       0
# CHECK-NEXT:    f32.const       0x0p0
# CHECK-NEXT:    end_try_table
# CHECK-NEXT:    drop
# CHECK-NEXT:    drop
# CHECK-NEXT:    end_block

# CHECK:         try_table
# CHECK-NEXT:    call    foo
# CHECK-NEXT:    end_try_table

# CHECK:         try_table       i32
# CHECK-NEXT:    i32.const       0
# CHECK-NEXT:    end_try_table
# CHECK-NEXT:    drop

# CHECK:         try_table       () -> (i32, f32)
# CHECK-NEXT:    i32.const       0
# CHECK-NEXT:    f32.const       0x0p0
# CHECK-NEXT:    end_try_table
# CHECK-NEXT:    drop
# CHECK-NEXT:    drop