# RUN: not llvm-mc -triple=wasm32 -mattr=+exception-handling,+reference-types,+tail-call %s 2>&1 | FileCheck %s
# These tests are intended to act as a litmus test for the WebAssembly ASM
# type-checker - both in terms of errors it can catch and in terms of the
# location information used in the error messages.
local_get_no_local_type:
.functype -> ()
# CHECK: :[[@LINE+1]]:13: error: no local type specified for index 0
local.get 0
end_function
local_set_no_local_type:
.functype -> ()
# CHECK: :[[@LINE+1]]:13: error: no local type specified for index 0
local.set 0
end_function
local_set_empty_stack_while_popping:
.functype -> ()
.local i32
# CHECK: [[@LINE+1]]:3: error: empty stack while popping i32
local.set 0
end_function
local_set_type_mismatch:
.functype -> ()
.local i32
f32.const 1.0
# CHECK: [[@LINE+1]]:3: error: popped f32, expected i32
local.set 0
end_function
local_tee_no_local_type:
.functype -> ()
# CHECK: :[[@LINE+1]]:13: error: no local type specified for index 0
local.tee 0
end_function
local_tee_empty_stack_while_popping:
.functype -> ()
.local f32
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping f32
local.tee 0
end_function
local_tee_type_mismatch:
.functype -> ()
.local f32
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: popped i32, expected f32
local.tee 0
end_function
global_get_missing_globaltype:
.functype -> ()
# CHECK: :[[@LINE+1]]:14: error: symbol foo missing .globaltype
global.get foo
end_function
global_get_expected_expression_operand:
.functype -> ()
# CHECK: :[[@LINE+1]]:14: error: expected expression operand
global.get 1
end_function
global_set_missing_globaltype:
.functype -> ()
# CHECK: :[[@LINE+1]]:14: error: symbol foo missing .globaltype
global.set foo
end_function
global_set_expected_expression_operand:
.functype -> ()
# CHECK: :[[@LINE+1]]:14: error: expected expression operand
global.set 1
end_function
global_set_empty_stack_while_popping:
.functype -> ()
.globaltype valid_global, i64
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i64
global.set valid_global
end_function
global_set_type_mismatch:
.functype -> ()
.globaltype valid_global, i64
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: popped i32, expected i64
global.set valid_global
end_function
table_get_expected_expression_operand:
.functype -> ()
# CHECK: :[[@LINE+1]]:13: error: expected expression operand
table.get 1
end_function
table_get_missing_tabletype:
.functype -> ()
# CHECK: :[[@LINE+1]]:13: error: symbol foo missing .tabletype
table.get foo
end_function
.tabletype valid_table, externref
table_get_empty_stack_while_popping:
.functype -> ()
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
table.get valid_table
end_function
table_get_type_mismatch:
.functype -> ()
f32.const 1.0
# CHECK: :[[@LINE+1]]:3: error: popped f32, expected i32
table.get valid_table
end_function
table_set_expected_expression_operand:
.functype -> ()
# CHECK: :[[@LINE+1]]:13: error: expected expression operand
table.set 1
end_function
table_set_missing_tabletype:
.functype -> ()
# CHECK: :[[@LINE+1]]:13: error: symbol foo missing .tabletype
table.set foo
end_function
table_set_empty_stack_while_popping_1:
.functype -> ()
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping externref
table.set valid_table
end_function
table_set_empty_stack_while_popping_2:
.functype -> ()
local.get 0
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
table.set valid_table
end_function
table_set_type_mismatch_1:
.functype -> ()
ref.null_func
# CHECK: :[[@LINE+1]]:3: error: popped funcref, expected externref
table.set valid_table
end_function
table_set_type_mismatch_2:
.functype -> ()
f32.const 1.0
ref.null_extern
# CHECK: :[[@LINE+1]]:3: error: popped f32, expected i32
table.set valid_table
end_function
table_fill_expected_expression_operand:
.functype -> ()
# CHECK: :[[@LINE+1]]:14: error: expected expression operand
table.fill 1
end_function
table_fill_missing_tabletype:
.functype -> ()
# CHECK: :[[@LINE+1]]:14: error: symbol foo missing .tabletype
table.fill foo
end_function
table_fill_empty_stack_while_popping_1:
.functype -> ()
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
table.fill valid_table
end_function
table_fill_empty_stack_while_popping_2:
.functype -> ()
local.get 0
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping externref
table.fill valid_table
end_function
table_fill_empty_stack_while_popping_3:
.functype -> ()
local.get 1
local.get 0
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
table.fill valid_table
end_function
table_fill_type_mismatch_1:
.functype -> ()
ref.null_func
# CHECK: :[[@LINE+1]]:3: error: popped funcref, expected i32
table.fill valid_table
end_function
table_fill_type_mismatch_2:
.functype -> ()
ref.null_func
i32.const 1
# CHECK: [[@LINE+1]]:3: error: popped funcref, expected externref
table.fill valid_table
end_function
table_fill_type_mismatch_3:
.functype -> ()
f32.const 2.0
ref.null_extern
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: popped f32, expected i32
table.fill valid_table
end_function
drop_empty_stack_while_popping:
.functype -> ()
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping value
drop
end_function
end_block_insufficient_values_on_stack:
.functype -> ()
block i32
# CHECK: :[[@LINE+1]]:3: error: end: insufficient values on the type stack
end_block
end_function
end_block_type_mismatch:
.functype -> ()
block i32
f32.const 1.0
# CHECK: :[[@LINE+1]]:3: error: end got f32, expected i32
end_block
end_function
end_loop_insufficient_values_on_stack:
.functype -> ()
loop i32
# CHECK: :[[@LINE+1]]:3: error: end: insufficient values on the type stack
end_loop
end_function
end_loop_type_mismatch:
.functype -> ()
loop f32
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: end got i32, expected f32
end_loop
end_function
end_if_insufficient_values_on_stack:
.functype -> ()
i32.const 1
if i32
# CHECK: :[[@LINE+1]]:3: error: end: insufficient values on the type stack
end_if
end_function
end_if_type_mismatch:
.functype -> ()
i32.const 1
if f32
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: end got i32, expected f32
end_if
end_function
else_insufficient_values_on_stack:
.functype -> ()
i32.const 1
if i32
i32.const 2
else
# FIXME: Should complain about insufficient values on the stack.
end_if
# FIXME: Should complain about superflous value on the stack.
end_function
else_type_mismatch:
.functype -> ()
i32.const 1
if i32
i32.const 2
else
# FIXME: Should complain about a type mismatch.
f32.const 3.0
end_if
drop
end_function
end_try_insufficient_values_on_stack:
.functype -> ()
try i32
# CHECK: :[[@LINE+1]]:3: error: end: insufficient values on the type stack
end_try
end_function
end_try_type_mismatch:
.functype -> ()
try i32
f32.const 1.0
# CHECK: :[[@LINE+1]]:3: error: end got f32, expected i32
end_try
end_function
end_function_empty_stack_while_popping:
.functype -> (i32)
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
end_function
end_function_type_mismatch:
.functype -> (f32)
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: popped i32, expected f32
end_function
end_function_superfluous_end_function_values:
.functype -> ()
i32.const 1
f32.const 2.0
# CHECK: :[[@LINE+1]]:3: error: 2 superfluous return values
end_function
return_empty_stack_while_popping:
.functype -> (i32)
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
return
end_function
return_type_mismatch:
.functype -> (f32)
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: popped i32, expected f32
return
end_function
# Missing index for call_indirect.
call_indirect_empty_stack_while_popping_1:
.functype -> ()
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
-> ()
end_function
# Missing arguments for target of call_indirect.
call_indirect_empty_stack_while_popping_2:
.functype -> ()
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping f32
-> ()
end_function
call_indirect_type_mismatch_for_argument:
.functype -> ()
i32.const 1
i32.const 2
# CHECK: :[[@LINE+1]]:3: error: popped i32, expected f32
-> ()
end_function
call_indirect_superfluous_value_at_end:
.functype -> ()
i32.const 1
-> (i64)
# CHECK: :[[@LINE+1]]:3: error: 1 superfluous return values
end_function
# Missing index for return_call_indirect.
return_call_indirect_empty_stack_while_popping_1:
.functype -> ()
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping i32
-> ()
end_function
# Missing arguments for target of return_call_indirect.
return_call_indirect_empty_stack_while_popping_2:
.functype -> ()
i32.const 1
# CHECK: :[[@LINE+1]]:3: error: empty stack while popping f32
-> ()
end_function
call_expected_expression_operand:
.functype -> ()
# CHECK: :[[@LINE+1]]:8: error: expected expression operand
call 1
end_function
.functype -> ()
call_empty_stack_while_popping:
.functype -> ()
# CHECK: [[@LINE+1]]:3: error: empty stack while popping i32
call fn_i32_to_void
end_function
call_type_mismatch:
.functype -> ()
f32.const 1.0
# CHECK: :[[@LINE+1]]:3: error: popped f32, expected i32
call fn_i32_to_void
end_function
.functype -> (i32)
call_superfluous_value_at_end:
.functype -> ()
call fn_void_to_i32
# CHECK: :[[@LINE+1]]:3: error: 1 superfluous return values
end_function
call_missing_functype:
.functype -> ()
# CHECK: :[[@LINE+1]]:8: error: symbol no_functype missing .functype
call no_functype
end_function
return_call_expected_expression_operand:
.functype -> ()
# CHECK: :[[@LINE+1]]:15: error: expected expression operand
return_call 1
end_function
return_call_empty_stack_while_popping:
.functype -> ()
# CHECK: [[@LINE+1]]:3: error: empty stack while popping i32
return_call fn_i32_to_void
end_function
return_call_type_mismatch:
.functype -> ()
f32.const 1.0
# CHECK: :[[@LINE+1]]:3: error: popped f32, expected i32
return_call fn_i32_to_void
end_function
return_call_missing_functype:
.functype -> ()
# CHECK: :[[@LINE+1]]:15: error: symbol no_functype missing .functype
return_call no_functype
end_function
catch_expected_expression_operand:
.functype -> ()
try
# CHECK: :[[@LINE+1]]:9: error: expected expression operand
catch 1
end_try
end_function
catch_missing_tagtype:
.functype -> ()
try
# CHECK: :[[@LINE+1]]:9: error: symbol no_tagtype missing .tagtype
catch no_tagtype
end_try
end_function
catch_superfluous_value_at_end:
.functype -> ()
.tagtype tag_i32 i32
try
catch tag_i32
end_try
# FIXME: Superfluous value should be caught at end_try?
# CHECK: :[[@LINE+1]]:3: error: 1 superfluous return values
end_function
ref_is_null_empty_stack_while_popping:
.functype -> ()
# CHECK: [[@LINE+1]]:3: error: empty stack while popping reftype
ref.is_null
end_function
ref_is_null_type_mismatch:
.functype -> ()
i32.const 1
# CHECK: [[@LINE+1]]:3: error: popped i32, expected reftype
ref.is_null
end_function
ref_is_null_pushes_i32:
.functype -> (i64)
ref.null_func
ref.is_null
# CHECK: :[[@LINE+1]]:3: error: popped i32, expected i64
end_function
# For the other instructions, the type checker checks vs the operands in the
# instruction definition. Perform some simple checks for these rather than
# exhaustively testing all instructions.
other_insn_test_1:
.functype -> ()
# CHECK: [[@LINE+1]]:3: error: empty stack while popping i32
i32.add
end_function
other_insn_test_2:
.functype -> ()
i32.const 1
ref.null_func
# CHECK: :[[@LINE+1]]:3: error: popped funcref, expected i32
i32.add
end_function
other_insn_test_3:
.functype -> ()
f32.const 1.0
f32.const 2.0
f32.add
# CHECK: :[[@LINE+1]]:3: error: 1 superfluous return values
end_function