Compiler projects using llvm
# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+tail-call,+reference-types,atomics,+simd128,+nontrapping-fptoint,+exception-handling < %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=+tail-call,+reference-types,+atomics,+simd128,+nontrapping-fptoint,+exception-handling -o %t.o < %s

.functype   something1 () -> ()
.functype   something2 (i64) -> (i32, f64)
.functype   something3 () -> (i32)
.globaltype __stack_pointer, i32

empty_func:
    .functype empty_func () -> ()
    end_function

test0:
# local labels can appear between label and its .functype.
.Ltest0begin:
    # Test all types:
    .functype   test0 (i32, i64) -> (i32)
    .tagtype  __cpp_exception i32
    .local      f32, f64, v128, v128
    # Explicit getlocal/setlocal:
    local.get   2
    local.set   2
    # Immediates:
    f32.const   -1.0
    drop
    f32.const   -infinity
    drop
    v128.const  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    drop
    v128.const  0, 1, 2, 3, 4, 5, 6, 7
    drop
    local.get   0
    f64.const   0x1.999999999999ap1
    # Indirect addressing:
    f64.store   1234:p2align=4
    i32.const   -1
    f64.const   nan
    f64.store   1234     # Natural alignment (3)
    # Loops, conditionals, binary ops, calls etc:
    block       f32
    f32.const   2.0
    i32.const   1
    local.get   0
    i32.ge_s
    br_if       0        # 0: down to label0
.LBB0_1:
    loop        void      # label1:
    call        something1
    i64.const   1234
    call        something2
    i32.const   0
    call_indirect (i32, f64) -> ()
    i32.const   1
    i32.const   2
    i32.add
    local.tee   0
    local.get   0
    i32.lt_s
    br_if       0        # 0: up to label1
.LBB0_2:
    end_loop
    end_block            # label0:
    drop
    block       i32
    block       void
    block       void
    block       void
    block       () -> (i32, i32)
    i32.const   1
    i32.const   2
    end_block
    drop
    br_table {0, 1, 2}   # 2 entries, default
    end_block            # first entry jumps here.
    i32.const   1
    br          2
    end_block            # second entry jumps here.
    i32.const   2
    br          1
    end_block            # default jumps here.
    i32.const   3
    end_block            # "switch" exit.
    if                   # void
    if          i32
    end_if
    else
    end_if
    drop
    block       void
    i32.const   2
    return
    end_block
    block       void
    return_call something3
    end_block
    block       void
    i32.const   3
    return_call_indirect () -> (i32)
    end_block
    local.get   4
    local.get   5
    f32x4.add
    drop
    # Test correct parsing of instructions with / and : in them:
    # TODO: enable once instruction has been added.
    #i32x4.trunc_sat_f32x4_s
    f32.const   1.0
    i32.trunc_f32_s
    try
    i32.atomic.load 0
    i32.const   0
    memory.atomic.notify 0
    drop
.LBB0_3:
    catch       __cpp_exception
    local.set   0
    end_try
    i32.const   .L.str
    i32.load8_u .L.str+2
    i32.load16_u .L.str:p2align=0
    throw 0
.LBB0_4:
    #i32.trunc_sat_f32_s
    global.get  __stack_pointer
    global.set  __stack_pointer
    end_function

    .section    .rodata..L.str,"",@
    .hidden     .L.str
    .type       .L.str,@object
.L.str:
    .int8       'H'
    .asciz      "ello, World!"
    .int16      1234
    .int64      5000000000
    .int32      2000000000
    .size       .L.str, 28

    .data
    .int8       73

    .section    .init_array.42,"",@
    .p2align    2
    .int32      test0

    .ident      "clang version 9.0.0 (trunk 364502) (llvm/trunk 364571)"

.tabletype empty_eref_table, externref
empty_eref_table:

.tabletype empty_fref_table, funcref
empty_fref_table:


# CHECK:           .text
# CHECK:           .globaltype __stack_pointer, i32

# CHECK-LABEL: empty_func:
# CHECK-NEXT:      .functype	empty_func () -> ()
# CHECK-NEXT:      end_function
# CHECK-LABEL: test0:
# CHECK-NEXT:  .Ltest0begin:
# CHECK-NEXT:      .functype   test0 (i32, i64) -> (i32)
# CHECK-NEXT:      .tagtype  __cpp_exception i32
# CHECK-NEXT:      .local      f32, f64
# CHECK-NEXT:      local.get   2
# CHECK-NEXT:      local.set   2
# CHECK-NEXT:      f32.const   -0x1p0
# CHECK-NEXT:      drop
# CHECK-NEXT:      f32.const   -infinity
# CHECK-NEXT:      drop
# CHECK-NEXT:      v128.const  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
# CHECK-NEXT:      drop
# CHECK-NEXT:      v128.const  0, 1, 2, 3, 4, 5, 6, 7
# CHECK-NEXT:      drop
# CHECK-NEXT:      local.get   0
# CHECK-NEXT:      f64.const   0x1.999999999999ap1
# CHECK-NEXT:      f64.store   1234:p2align=4
# CHECK-NEXT:      i32.const   -1
# CHECK-NEXT:      f64.const   nan
# CHECK-NEXT:      f64.store   1234
# CHECK-NEXT:      block       f32
# CHECK-NEXT:      f32.const   0x1p1
# CHECK-NEXT:      i32.const   1
# CHECK-NEXT:      local.get   0
# CHECK-NEXT:      i32.ge_s
# CHECK-NEXT:      br_if       0       # 0: down to label0
# CHECK-NEXT:  .LBB0_1:
# CHECK-NEXT:      loop                # label1:
# CHECK-NEXT:      call        something1
# CHECK-NEXT:      i64.const   1234
# CHECK-NEXT:      call        something2
# CHECK-NEXT:      i32.const   0
# CHECK-NEXT:      call_indirect __indirect_function_table, (i32, f64) -> ()
# CHECK-NEXT:      i32.const   1
# CHECK-NEXT:      i32.const   2
# CHECK-NEXT:      i32.add
# CHECK-NEXT:      local.tee   0
# CHECK-NEXT:      local.get   0
# CHECK-NEXT:      i32.lt_s
# CHECK-NEXT:      br_if       0       # 0: up to label1
# CHECK-NEXT:  .LBB0_2:
# CHECK-NEXT:      end_loop
# CHECK-NEXT:      end_block           # label0:
# CHECK-NEXT:      drop
# CHECK-NEXT:      block       i32
# CHECK-NEXT:      block
# CHECK-NEXT:      block
# CHECK-NEXT:      block
# CHECK-NEXT:      block       () -> (i32, i32)
# CHECK-NEXT:      i32.const   1
# CHECK-NEXT:      i32.const   2
# CHECK-NEXT:      end_block
# CHECK-NEXT:      drop
# CHECK-NEXT:      br_table {0, 1, 2}  # 1: down to label4
# CHECK-NEXT:                          # 2: down to label3
# CHECK-NEXT:      end_block           # label5:
# CHECK-NEXT:      i32.const   1
# CHECK-NEXT:      br          2       # 2: down to label2
# CHECK-NEXT:      end_block           # label4:
# CHECK-NEXT:      i32.const   2
# CHECK-NEXT:      br          1       # 1: down to label2
# CHECK-NEXT:      end_block           # label3:
# CHECK-NEXT:      i32.const   3
# CHECK-NEXT:      end_block           # label2:
# CHECK-NEXT:      if
# CHECK-NEXT:      if          i32
# CHECK-NEXT:      end_if
# CHECK-NEXT:      else
# CHECK-NEXT:      end_if
# CHECK-NEXT:      drop
# CHECK-NEXT:      block
# CHECK-NEXT:      i32.const   2
# CHECK-NEXT:      return
# CHECK-NEXT:      end_block
# CHECK-NEXT:      block
# CHECK-NEXT:      return_call something3
# CHECK-NEXT:      end_block
# CHECK-NEXT:      block
# CHECK-NEXT:      i32.const   3
# CHECK-NEXT:      return_call_indirect __indirect_function_table, () -> (i32)
# CHECK-NEXT:      end_block
# CHECK-NEXT:      local.get   4
# CHECK-NEXT:      local.get   5
# CHECK-NEXT:      f32x4.add
# CHECK-NEXT:      drop
# CHECK-NEXT:      f32.const   0x1p0
# CHECK-NEXT:      i32.trunc_f32_s
# CHECK-NEXT:      try
# CHECK-NEXT:      i32.atomic.load 0
# CHECK-NEXT:      i32.const   0
# CHECK-NEXT:      memory.atomic.notify 0
# CHECK-NEXT:      drop
# CHECK-NEXT:  .LBB0_3:
# CHECK-NEXT:      catch       __cpp_exception
# CHECK-NEXT:      local.set   0
# CHECK-NEXT:      end_try
# CHECK-NEXT:      i32.const   .L.str
# CHECK-NEXT:      i32.load8_u .L.str+2
# CHECK-NEXT:      i32.load16_u .L.str:p2align=0
# CHECK-NEXT:      throw       0
# CHECK-NEXT:  .LBB0_4:
# CHECK-NEXT:      global.get  __stack_pointer
# CHECK-NEXT:      global.set  __stack_pointer
# CHECK-NEXT:      end_function

# CHECK:           .section    .rodata..L.str,"",@
# CHECK-NEXT:      .hidden     .L.str
# CHECK-NEXT:  .L.str:
# CHECK-NEXT:      .int8       72
# CHECK-NEXT:      .asciz      "ello, World!"
# CHECK-NEXT:      .int16      1234
# CHECK-NEXT:      .int64      5000000000
# CHECK-NEXT:      .int32      2000000000
# CHECK-NEXT:      .size       .L.str, 28

# CHECK:           .data
# CHECK-EMPTY:
# CHECK-NEXT:      .int8       73

# CHECK:           .section    .init_array.42,"",@
# CHECK-NEXT:      .p2align    2
# CHECK-NEXT:      .int32      test0

# CHECK:           .tabletype empty_eref_table, externref
# CHECK-NEXT: empty_eref_table:

# CHECK:           .tabletype empty_fref_table, funcref
# CHECK-NEXT: empty_fref_table: