From b1d83e2ccd060ec8942cf310bca59c4de3866f21 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 21 Jun 2022 14:44:28 +0200 Subject: [PATCH] Auto-import std::core. Fix module assignment of declarations. Introspection improvements. Deref null error panics in safe mode. Support for LLVM 15 --- .github/workflows/main.yml | 8 +- CMakeLists.txt | 7 +- lib/std/array.c3 | 1 - lib/std/{ => core}/builtin.c3 | 30 +- lib/std/{ => core}/cinterop.c3 | 2 +- lib/std/{ => core}/env.c3 | 2 +- lib/std/{ => core}/mem.c3 | 7 +- lib/std/{ => core}/mem_allocator.c3 | 2 +- lib/std/{ => core}/mem_allocator_fn.c3 | 2 +- lib/std/{ => core}/mem_temp_allocator.c3 | 2 +- lib/std/{ => core}/os/linux.c3 | 3 +- lib/std/{ => core}/os/macos.c3 | 4 +- lib/std/{ => core}/os/windows.c3 | 3 +- lib/std/core/str.c3 | 166 +++ lib/std/core/string.c3 | 255 ++++ lib/std/core/string_iterator.c3 | 25 + lib/std/io.c3 | 2 - lib/std/libc.c3 | 5 - lib/std/linkedlist.c3 | 1 - lib/std/list.c3 | 1 - lib/std/str.c3 | 59 - src/build/build_options.c | 25 +- src/build/build_options.h | 5 + src/build/builder.c | 37 +- src/compiler/compiler.c | 21 + src/compiler/compiler_internal.h | 6 +- src/compiler/context.c | 2 + src/compiler/enums.h | 23 + src/compiler/llvm_codegen.c | 108 +- src/compiler/llvm_codegen_expr.c | 121 +- src/compiler/llvm_codegen_internal.h | 17 +- src/compiler/llvm_codegen_module.c | 32 +- src/compiler/llvm_codegen_stmt.c | 49 +- src/compiler/llvm_codegen_type.c | 324 +++++ src/compiler/sema_casts.c | 2 +- src/compiler/sema_decls.c | 11 +- src/compiler/sema_expr.c | 10 +- src/compiler/sema_name_resolution.c | 4 +- src/compiler/semantic_analyser.c | 2 +- src/compiler/symtab.c | 5 +- src/compiler/types.c | 1 - src/main.c | 2 + src/version.h | 2 +- test/src/tester.py | 13 +- test/test_suite/abi/regcall_expand.c3t | 4 +- test/test_suite/assert/unreachable.c3t | 2 +- .../attributes/user_defined_attributes.c3t | 2 +- .../enumerations/enum_associated_value.c3t | 15 +- test/test_suite/errors/anyerr_void.c3t | 6 +- test/test_suite/errors/error_else.c3t | 22 + test/test_suite/errors/error_regression_2.c3t | 36 +- test/test_suite/errors/failable_inits.c3t | 4 +- .../errors/failable_taddr_and_access.c3t | 8 +- .../errors/general_error_regression.c3t | 14 +- test/test_suite/errors/macro_err2.c3t | 2 +- .../errors/simple_static_failable.c3t | 4 +- .../test_suite/expressions/pointer_access.c3t | 10 +- test/test_suite/failable_catch.c3t | 232 ++-- .../from_docs/examples_forswitch.c3t | 4 +- .../from_docs/examples_if_catch.c3t | 5 +- test/test_suite/functions/test_regression.c3t | 27 +- .../functions/test_regression_mingw.c3t | 49 +- .../test_suite/functions/typeless_varargs.c3t | 6 +- test/test_suite/import/import_error.c3 | 2 +- test/test_suite/import/import_works.c3t | 2 +- .../initializer_lists/general_tests.c3t | 4 +- test/test_suite/initializer_lists/statics.c3t | 5 +- .../initializer_lists/subarrays.c3t | 6 +- test/test_suite/macros/userland_bitcast.c3t | 47 +- .../pointers/subarray_variant_to_ptr.c3t | 7 +- test/test_suite/safe/deref.c3t | 29 + .../statements/custom_foreach_with_ref.c3t | 2 +- test/test_suite/struct/struct_as_value.c3t | 5 +- test/test_suite/struct/struct_codegen.c3t | 6 +- .../struct/struct_codegen_empty.c3t | 3 +- .../struct/struct_const_construct_simple.c3t | 5 +- test/test_suite/variant/variant_assign.c3t | 40 +- test/test_suite/variant/variant_switch.c3t | 16 +- test/test_suite/variant/variant_test.c3t | 42 +- test/test_suite/vector/vector_ops2.c3t | 12 +- test/test_suite2/abi/aarch64_args.c3t | 29 + test/test_suite2/abi/aarch64_hfa_args.c3t | 32 + test/test_suite2/abi/darwin64_avx.c3t | 141 ++ test/test_suite2/abi/darwin64_avx512.c3t | 74 ++ test/test_suite2/abi/darwin64_sse.c3t | 56 + test/test_suite2/abi/darwinx64_1.c3t | 48 + test/test_suite2/abi/darwinx64_2.c3t | 186 +++ test/test_suite2/abi/literal_load.c3t | 32 + test/test_suite2/abi/literal_load_aarch64.c3t | 36 + test/test_suite2/abi/literal_load_mingw.c3t | 33 + .../abi/macho_section_attributes.c3 | 8 + test/test_suite2/abi/pass_large_aarch.c3t | 32 + test/test_suite2/abi/regcall_expand.c3t | 57 + test/test_suite2/abi/riscv64-lp64-abi.c3t | 51 + test/test_suite2/abi/small_struct_x64.c3t | 66 + test/test_suite2/abi/sysv_direct_coerce.c3t | 43 + test/test_suite2/abi/test_sret.c3t | 38 + test/test_suite2/abi/union_x64.c3t | 37 + test/test_suite2/abi/vec2_aarch64.c3t | 95 ++ test/test_suite2/abi/vec2_wasm.c3t | 98 ++ test/test_suite2/abi/vec2_x64.c3t | 107 ++ test/test_suite2/abi/x64alignarray.c3t | 27 + test/test_suite2/arrays/array_casts.c3t | 32 + .../test_suite2/arrays/array_invalid_casts.c3 | 12 + test/test_suite2/arrays/array_literal.c3t | 27 + test/test_suite2/arrays/array_struct.c3t | 13 + .../arrays/complex_array_const.c3t | 22 + .../arrays/global_array_non_const.c3 | 17 + test/test_suite2/arrays/index_from_back.c3t | 57 + test/test_suite2/arrays/index_into_global.c3t | 33 + test/test_suite2/arrays/inferred_array_err.c3 | 7 + .../test_suite2/arrays/inferred_array_err2.c3 | 5 + test/test_suite2/arrays/negative_array.c3 | 5 + test/test_suite2/arrays/slice.c3 | 7 + test/test_suite2/assert/assert_variants.c3t | 62 + .../global_static_assert_not_constant.c3 | 3 + .../local_static_assert_not_constant.c3 | 20 + test/test_suite2/assert/static_assert.c3 | 8 + test/test_suite2/assert/unreachable.c3t | 40 + test/test_suite2/assignment/int_assign.c3t | 69 + .../attributes/recursive_attributes.c3 | 17 + .../attributes/user_defined_attributes.c3t | 45 + .../bitstruct/address_of_bitstruct.c3 | 15 + .../bitstruct/array_with_boolean.c3t | 71 + .../test_suite2/bitstruct/bitfield_access.c3t | 180 +++ .../bitstruct/bitstruct_access_signed.c3t | 91 ++ .../bitstruct/bitstruct_arrays.c3t | 1148 +++++++++++++++++ .../bitstruct/bitstruct_arrays_be.c3t | 144 +++ .../bitstruct/bitstruct_general.c3 | 46 + test/test_suite2/bitstruct/bitstruct_init.c3 | 62 + .../bitstruct/bitstruct_intcontainer.c3t | 105 ++ .../bitstruct/bitstruct_overlap.c3 | 47 + .../bitstruct/bitstruct_single_error.c3 | 19 + .../bitstruct/bitstruct_to_int.c3t | 103 ++ .../bitstruct/embedded_bitstruct.c3t | 79 ++ .../invalid_bitstruct_member_types.c3 | 26 + .../invalid_bitstruct_name_other_ident.c3 | 20 + .../bitstruct/invalid_bitstruct_type.c3 | 7 + .../bitstruct/invalid_empty_struct_union.c3 | 7 + .../bitstruct/missing_bitstruct_type.c3 | 3 + test/test_suite2/builtins/simple_builtins.c3t | 57 + test/test_suite2/cast/cast_from_ptr.c3t | 22 + test/test_suite2/cast/cast_ok.c3 | 11 + test/test_suite2/cast/cast_parse_fails.c3 | 13 + test/test_suite2/cast/cast_parse_fails2.c3 | 8 + test/test_suite2/cast/cast_struct.c3 | 37 + test/test_suite2/cast/cast_struct_fails.c3 | 35 + test/test_suite2/cast/cast_to_failable.c3 | 12 + test/test_suite2/cast/top_down_cast_fails.c3 | 29 + test/test_suite2/cast/top_down_casts.c3t | 101 ++ test/test_suite2/clang/2002-01_02.c3t | 346 +++++ test/test_suite2/clang/2002-03.c3t | 98 ++ test/test_suite2/clang/2002-04.c3t | 166 +++ test/test_suite2/comments/simple_comments.c3 | 15 + .../compile_time/compile_time_array.c3t | 28 + .../compile_time/compile_time_array_ref.c3t | 24 + .../compile_time/compile_time_bitops.c3t | 18 + .../compile_time/compile_time_ptr_ref.c3t | 22 + test/test_suite2/compile_time/ct_eval.c3t | 22 + test/test_suite2/compile_time/ct_for.c3t | 32 + test/test_suite2/compile_time/ct_foreach.c3t | 52 + test/test_suite2/compile_time/ct_if.c3t | 65 + test/test_suite2/compile_time/ct_if_fails.c3 | 28 + test/test_suite2/compile_time/ct_switch.c3t | 65 + .../compile_time/ct_switch_errors.c3 | 36 + .../compile_time/ct_switch_top_level.c3t | 54 + .../compile_time/ct_switch_type_check.c3t | 46 + .../compile_time/ct_switch_type_errors.c3 | 51 + .../compile_time/cttype_reassign.c3t | 15 + .../compile_time/not_yet_initialized.c3 | 17 + test/test_suite2/compile_time/stringify.c3t | 109 ++ .../compile_time/ternary_folding.c3t | 25 + .../compile_time/typeof_example.c3t | 52 + .../compile_time/typeof_from_literal.c3 | 14 + .../compile_time_introspection/alignof.c3t | 90 ++ .../compile_time_introspection/defined.c3t | 97 ++ .../defined_builtin.c3t | 18 + .../compile_time_introspection/defined_err.c3 | 25 + .../compile_time_introspection/nameof.c3t | 68 + .../compile_time_introspection/nameof_err.c3 | 20 + .../compile_time_introspection/offsetof.c3t | 70 + .../compile_time_introspection/qnameof.c3t | 59 + .../compile_time_introspection/sizeof.c3t | 66 + .../sizeof_errors.c3 | 67 + .../constants/byte_literal_fail_base64.c3 | 1 + .../constants/byte_literal_fail_base64_2.c3 | 1 + .../constants/byte_literal_fail_base64_4.c3 | 1 + .../constants/byte_literal_fail_hex.c3 | 1 + test/test_suite2/constants/byte_literals.c3t | 13 + test/test_suite2/constants/char_literals.c3t | 24 + test/test_suite2/constants/const_var_copy.c3t | 29 + test/test_suite2/constants/constants.c3t | 40 + .../contracts/ct_eval_of_ensure.c3 | 16 + test/test_suite2/contracts/pure.c3 | 24 + test/test_suite2/contracts/pure_calls.c3 | 26 + test/test_suite2/contracts/simple_test.c3t | 90 ++ test/test_suite2/debug_symbols/constants.c3t | 28 + .../defer/defer_and_expr_block.c3t | 40 + test/test_suite2/defer/defer_single_stmt.c3 | 41 + test/test_suite2/defer/defer_static_var.c3t | 205 +++ test/test_suite2/defer/defer_with_rethrow.c3 | 14 + test/test_suite2/defer/defer_with_return.c3 | 10 + test/test_suite2/define/common.c3 | 17 + test/test_suite2/define/define_name_errors.c3 | 9 + test/test_suite2/define/forbidden_defines.c3 | 3 + test/test_suite2/distinct/distinct_invalid.c3 | 8 + test/test_suite2/distinct/distinct_struct.c3 | 28 + .../distinct/distinct_struct_array.c3 | 19 + test/test_suite2/distinct/distinct_union.c3 | 34 + test/test_suite2/distinct/test_errors.c3 | 11 + test/test_suite2/distinct/test_ops_on_int.c3 | 29 + .../distinct/test_ops_on_struct.c3 | 24 + .../test_suite2/enumerations/compile_time.c3t | 16 + .../enumerations/enum_associated_value.c3t | 51 + test/test_suite2/enumerations/enum_cast.c3t | 99 ++ test/test_suite2/enumerations/enum_values.c3t | 40 + .../enumerations/simple_inference.c3t | 23 + test/test_suite2/errors/anyerr_void.c3t | 88 ++ test/test_suite2/errors/bitshift_failable.c3 | 5 + test/test_suite2/errors/else_checks.c3t | 111 ++ test/test_suite2/errors/error_decl_ok.c3 | 19 + test/test_suite2/errors/error_else.c3t | 22 + .../test_suite2/errors/error_regression_2.c3t | 900 +++++++++++++ .../errors/error_semantic_fails.c3 | 5 + test/test_suite2/errors/error_throw.c3 | 12 + test/test_suite2/errors/error_union.c3 | 11 + test/test_suite2/errors/failable_inits.c3t | 113 ++ .../errors/failable_taddr_and_access.c3t | 120 ++ .../errors/failable_untyped_list.c3 | 24 + .../errors/general_error_regression.c3t | 141 ++ .../errors/illegal_use_of_failable.c3 | 14 + test/test_suite2/errors/macro_err.c3t | 54 + test/test_suite2/errors/macro_err2.c3t | 59 + test/test_suite2/errors/macro_err3.c3t | 37 + test/test_suite2/errors/no_common.c3 | 13 + test/test_suite2/errors/or_err_bool.c3t | 34 + test/test_suite2/errors/precedence_err.c3 | 5 + test/test_suite2/errors/rethrow.c3t | 33 + test/test_suite2/errors/rethrow_mingw.c3t | 39 + test/test_suite2/errors/rethrow_no_err.c3 | 17 + .../errors/simple_static_failable.c3t | 24 + test/test_suite2/errors/try_assign.c3t | 152 +++ test/test_suite2/errors/try_catch_if.c3t | 99 ++ .../errors/try_catch_unwrapping_while_if.c3 | 98 ++ .../errors/try_unwrap_using_assert.c3t | 41 + .../errors/try_with_assign_to_failable.c3 | 6 + .../errors/try_with_chained_unwrap.c3t | 58 + .../errors/try_with_chained_unwrap_errors.c3 | 93 ++ test/test_suite2/errors/try_with_unwrap.c3t | 84 ++ .../test_suite2/errors/try_with_unwrapper.c3t | 184 +++ .../errors/try_with_weird_stuff.c3 | 16 + test/test_suite2/examples/gameoflife.c3 | 90 ++ .../expression_block_break.c3 | 13 + .../test_suite2/expressions/addr_compiles.c3t | 142 ++ test/test_suite2/expressions/addr_of_fails.c3 | 78 ++ test/test_suite2/expressions/arithmetics.c3 | 40 + .../expressions/arithmetics_sema_fail.c3 | 91 ++ test/test_suite2/expressions/assign.c3 | 5 + test/test_suite2/expressions/assignability.c3 | 39 + .../expressions/assignment_precedence.c3t | 23 + .../test_suite2/expressions/call_arg_types.c3 | 19 + test/test_suite2/expressions/call_inline.c3t | 49 + .../expressions/casts/cast_const.c3 | 6 + .../expressions/casts/cast_enum_to_various.c3 | 39 + .../expressions/casts/cast_expr.c3t | 27 + .../expressions/casts/cast_failable.c3 | 10 + .../expressions/casts/cast_func_to_various.c3 | 45 + .../expressions/casts/cast_to_nonscalar.c3 | 9 + .../expressions/casts/cast_unknown.c3 | 21 + .../expressions/casts/explicit_cast.c3 | 15 + .../expressions/casts/narrowing.c3 | 7 + .../expressions/chained_conditional.c3t | 69 + ...eck_implict_conversion_signed_unsigned.c3t | 23 + test/test_suite2/expressions/elvis.c3t | 69 + .../expressions/fail_index_usize.c3 | 5 + test/test_suite2/expressions/folding_ptr.c3t | 34 + test/test_suite2/expressions/incdec.c3t | 44 + test/test_suite2/expressions/negate_int.c3 | 41 + .../expressions/no_valid_conversion_minus.c3 | 10 + .../expressions/parsed_numbers.c3t | 13 + .../expressions/pointer_access.c3t | 104 ++ test/test_suite2/expressions/pointer_arith.c3 | 18 + .../expressions/pointer_conv_error.c3 | 18 + .../expressions/pointer_to_bool.c3 | 9 + test/test_suite2/expressions/rvalues.c3 | 16 + .../expressions/simple_float_sub_neg.c3t | 17 + test/test_suite2/expressions/strings.c3t | 10 + test/test_suite2/expressions/ternary_bool.c3t | 110 ++ .../expressions/ternary_no_ident.c3 | 14 + .../expressions/unsafe_comparisons.c3 | 41 + test/test_suite2/failable_catch.c3t | 176 +++ test/test_suite2/floats/convert_float.c3t | 24 + .../explicit_float_truncation_needed.c3 | 4 + .../floats/float_exceeding_size.c3 | 5 + test/test_suite2/floats/inf_nan.c3t | 26 + test/test_suite2/from_docs/examples_defer.c3t | 61 + .../from_docs/examples_forswitch.c3t | 237 ++++ .../from_docs/examples_functionpointer.c3t | 34 + .../from_docs/examples_if_catch.c3t | 161 +++ .../from_docs/examples_macro_function.c3t | 50 + test/test_suite2/from_docs/examples_struct.c3 | 46 + test/test_suite2/functions/assorted_tests.c3t | 110 ++ .../functions/body_argument_fail.c3 | 5 + .../functions/default_param_fail.c3 | 11 + test/test_suite2/functions/double_return.c3t | 13 + test/test_suite2/functions/macro_arguments.c3 | 10 + .../functions/missing_first_paren.c3 | 3 + test/test_suite2/functions/missing_return.c3 | 3 + test/test_suite2/functions/naked_function.c3t | 15 + .../functions/naked_function_fail.c3 | 4 + test/test_suite2/functions/returning_void.c3t | 20 + test/test_suite2/functions/splat.c3t | 68 + test/test_suite2/functions/splat_aarch64.c3t | 71 + test/test_suite2/functions/splat_mingw.c3t | 61 + test/test_suite2/functions/static_vars.c3t | 22 + .../test_suite2/functions/test_regression.c3t | 678 ++++++++++ .../functions/test_regression_mingw.c3t | 731 +++++++++++ .../functions/typeless_varargs.c3t | 101 ++ .../functions/vararg_argument_fails.c3 | 5 + test/test_suite2/functions/varargs.c3t | 42 + test/test_suite2/generic/generic_copy.c3t | 12 + test/test_suite2/generic/generic_idents.c3t | 69 + test/test_suite2/globals/external_global.c3t | 35 + test/test_suite2/globals/global_align.c3t | 22 + test/test_suite2/globals/global_extname.c3t | 7 + test/test_suite2/globals/global_init.c3 | 23 + test/test_suite2/globals/misplaced_const.c3 | 6 + test/test_suite2/globals/recursive_globals.c3 | 3 + test/test_suite2/globals/recursive_locals.c3 | 13 + .../globals/self_referencing_local.c3 | 5 + test/test_suite2/globals/static_global.c3 | 1 + .../import/access_other_module.c3t | 24 + test/test_suite2/import/autoimport.c3 | 36 + test/test_suite2/import/import_error.c3 | 6 + test/test_suite2/import/import_error_multi.c3 | 1 + .../import/import_error_out_of_order.c3 | 5 + .../test_suite2/import/import_error_string.c3 | 1 + test/test_suite2/import/import_implicit.c3 | 17 + test/test_suite2/import/import_works.c3t | 3 + .../initializer_lists/disallowed_lists.c3 | 8 + test/test_suite2/initializer_lists/fasta.c3t | 373 ++++++ .../initializer_lists/general_tests.c3t | 96 ++ .../indexing_into_complist.c3 | 28 + .../initializer_lists/ranges_to_dynamic.c3t | 64 + .../test_suite2/initializer_lists/statics.c3t | 90 ++ .../initializer_lists/subarrays.c3t | 170 +++ .../initializer_lists/zero_init.c3t | 69 + test/test_suite2/lexing/expected_directive.c3 | 4 + .../lexing/invalid_hex_in_hexarray.c3 | 1 + .../lexing/invalid_hex_in_hexarray2.c3 | 1 + test/test_suite2/lexing/no_builtin.c3 | 2 + test/test_suite2/literals/bad_bitwidth.c3 | 4 + test/test_suite2/literals/literal_general.c3t | 22 + test/test_suite2/literals/multi_unicode.c3 | 1 + .../literals/radix_numbers_errors.c3 | 17 + test/test_suite2/literals/too_small.c3 | 2 + test/test_suite2/macro_methods/access.c3 | 35 + .../macro_methods/macro_method_fails.c3 | 46 + .../macro_methods_defined_twice.c3 | 31 + test/test_suite2/macros/hash_ident.c3 | 24 + .../test_suite2/macros/macro_body_as_value.c3 | 12 + test/test_suite2/macros/macro_body_defer.c3t | 126 ++ test/test_suite2/macros/macro_body_errors.c3 | 7 + test/test_suite2/macros/macro_calls_prefix.c3 | 11 + test/test_suite2/macros/macro_common.c3t | 52 + .../macros/macro_convert_literal.c3 | 12 + test/test_suite2/macros/macro_defer_exit.c3t | 83 ++ test/test_suite2/macros/macro_defer_scope.c3t | 43 + .../macros/macro_defer_with_body.c3t | 55 + .../macros/macro_import_res_private.c3t | 26 + .../macros/macro_import_resolution.c3 | 13 + .../macros/macro_nested_labels.c3t | 356 +++++ test/test_suite2/macros/macro_resolution.c3 | 24 + test/test_suite2/macros/macro_rtype.c3 | 9 + test/test_suite2/macros/macro_with_body.c3t | 106 ++ test/test_suite2/macros/no_body.c3 | 50 + test/test_suite2/macros/type_params.c3t | 42 + test/test_suite2/macros/userland_bitcast.c3t | 332 +++++ test/test_suite2/methods/access.c3 | 37 + .../methods/enum_distinct_err_methods.c3t | 76 ++ test/test_suite2/methods/extension_method.c3t | 40 + .../methods/extension_method_already_exist.c3 | 30 + .../methods/methods_defined_twice.c3 | 31 + test/test_suite2/module/missing_semi.c3 | 3 + .../module/module_bad_path_ident.c3 | 1 + .../module/module_bad_path_invalid.c3 | 1 + .../module/module_bad_path_keyword.c3 | 1 + .../test_suite2/module/module_error_string.c3 | 1 + .../module/module_start_bad_ident.c3 | 1 + .../module/module_start_invalid.c3 | 1 + .../module/module_start_keyword.c3 | 1 + test/test_suite2/module/private_module.c3 | 1 + test/test_suite2/module/unknown_modules.c3 | 4 + .../pointers/array_pointer_decay.c3t | 78 ++ test/test_suite2/pointers/const_pointer.c3t | 16 + test/test_suite2/pointers/pointer_index.c3t | 78 ++ .../pointers/subarray_variant_to_ptr.c3t | 96 ++ .../test_suite2/precedence/required_parens.c3 | 13 + .../regression/crash_on_right_paren_macro.c3 | 6 + test/test_suite2/safe/deref.c3t | 30 + test/test_suite2/slices/slice_assign.c3t | 90 ++ test/test_suite2/statements/binary_fail.c3 | 9 + .../statements/call_missing_paren.c3 | 7 + .../statements/comparison_widening.c3t | 34 + .../statements/conditional_return.c3 | 12 + .../statements/custom_foreach_with_ref.c3t | 480 +++++++ test/test_suite2/statements/default_args.c3 | 2 + test/test_suite2/statements/defer_break.c3t | 114 ++ .../statements/defer_break_simple.c3t | 58 + .../statements/defer_break_switch.c3t | 59 + .../test_suite2/statements/defer_do_while.c3t | 38 + .../test_suite2/statements/defer_in_block.c3t | 87 ++ .../test_suite2/statements/defer_in_defer.c3t | 38 + .../statements/defer_in_defer2.c3t | 120 ++ .../statements/defer_next_switch.c3t | 59 + test/test_suite2/statements/defer_return.c3t | 100 ++ test/test_suite2/statements/defer_test.c3 | 9 + .../statements/defer_with_loop.c3t | 108 ++ .../statements/do_without_compound.c3 | 5 + test/test_suite2/statements/fallthough_do.c3t | 81 ++ test/test_suite2/statements/for.c3 | 27 + test/test_suite2/statements/for_empty.c3 | 7 + test/test_suite2/statements/for_errors.c3 | 7 + .../statements/for_with_extra_declarations.c3 | 17 + test/test_suite2/statements/foreach_break.c3t | 74 ++ .../test_suite2/statements/foreach_common.c3t | 366 ++++++ .../test_suite2/statements/foreach_custom.c3t | 82 ++ .../statements/foreach_custom_errors.c3 | 15 + .../statements/foreach_custom_macro.c3t | 105 ++ test/test_suite2/statements/foreach_errors.c3 | 54 + .../statements/foreach_parse_error.c3 | 5 + .../statements/foreach_with_error.c3 | 12 + test/test_suite2/statements/if_decl.c3 | 5 + test/test_suite2/statements/if_single.c3 | 29 + test/test_suite2/statements/if_tests.c3t | 71 + .../statements/if_while_do_error.c3 | 34 + test/test_suite2/statements/label_errors.c3 | 24 + .../statements/labelled_continue_for.c3t | 71 + test/test_suite2/statements/ranged_switch.c3t | 230 ++++ test/test_suite2/statements/return_stmt.c3 | 11 + test/test_suite2/statements/return_switch.c3t | 36 + .../statements/return_with_other_at_end.c3 | 7 + test/test_suite2/statements/simple_do.c3t | 113 ++ .../statements/switch_error_range.c3 | 12 + test/test_suite2/statements/switch_errors.c3 | 160 +++ .../statements/various_switching.c3t | 57 + .../statements/while_statement_placement.c3 | 11 + test/test_suite2/statements/while_switch.c3t | 92 ++ test/test_suite2/strings/literal_errors.c3 | 22 + test/test_suite2/strings/literal_hex_ok.c3 | 3 + .../strings/literal_to_subarray.c3t | 24 + .../test_suite2/strings/multiline_strings.c3t | 18 + test/test_suite2/strings/string_escape.c3t | 22 + test/test_suite2/strings/string_len.c3t | 7 + test/test_suite2/strings/string_to_array.c3t | 23 + test/test_suite2/struct/duplicate_member.c3 | 69 + .../struct/flex_array_struct_err.c3 | 31 + test/test_suite2/struct/func_return_struct.c3 | 12 + test/test_suite2/struct/member_access.c3 | 87 ++ test/test_suite2/struct/member_expr.c3 | 31 + test/test_suite2/struct/recursive_structs.c3 | 25 + test/test_suite2/struct/simple_struct.c3t | 14 + test/test_suite2/struct/struct_as_value.c3t | 48 + .../struct/struct_as_value_aarch64.c3t | 42 + test/test_suite2/struct/struct_codegen.c3t | 27 + .../struct/struct_codegen_empty.c3t | 39 + .../test_suite2/struct/struct_codegen_fam.c3t | 32 + .../struct/struct_const_construct_simple.c3t | 34 + .../struct/struct_pack_and_align.c3t | 101 ++ test/test_suite2/struct/struct_params.c3 | 27 + test/test_suite2/struct/zero_member.c3 | 7 + .../subarrays/slice_comparison.c3t | 232 ++++ .../subarrays/slice_negative_len.c3 | 72 ++ test/test_suite2/subarrays/slice_offset.c3t | 19 + .../subarrays/slice_offset_neg_end.c3t | 20 + .../subarrays/slice_offset_neg_start.c3t | 19 + test/test_suite2/subarrays/slice_start.c3t | 19 + test/test_suite2/subarrays/slice_syntax.c3 | 24 + test/test_suite2/subarrays/sub_array_init.c3 | 7 + test/test_suite2/switch/failable_switch.c3 | 14 + .../symbols/allow_local_shadowing.c3 | 10 + test/test_suite2/symbols/shadow_struct.c3 | 15 + test/test_suite2/symbols/various.c3 | 189 +++ test/test_suite2/types/enum_illegal_type.c3 | 9 + .../types/enum_implicit_overflow.c3 | 136 ++ test/test_suite2/types/enum_inference.c3 | 43 + test/test_suite2/types/enum_ok.c3 | 35 + test/test_suite2/types/enum_param.c3 | 12 + test/test_suite2/types/enum_parse_errors.c3 | 22 + test/test_suite2/types/recursive_array.c3 | 4 + test/test_suite2/types/recursive_typedef.c3 | 9 + test/test_suite2/types/redefinition.c3 | 2 + test/test_suite2/types/typedefs.c3 | 11 + test/test_suite2/types/various.c3 | 5 + test/test_suite2/unicode/commenting-out.c3 | 10 + .../test_suite2/union/flexible_array_union.c3 | 5 + test/test_suite2/union/test_unions.c3 | 28 + .../test_suite2/union/union_codegen_const.c3t | 20 + .../test_suite2/union/union_codegen_empty.c3t | 44 + .../union/union_codegen_overwrite_call.c3t | 29 + test/test_suite2/union/union_in_struct.c3t | 45 + .../union/union_member_voidcast.c3 | 13 + test/test_suite2/variables/consts.c3 | 7 + test/test_suite2/variant/variant_assign.c3t | 335 +++++ test/test_suite2/variant/variant_switch.c3t | 142 ++ test/test_suite2/variant/variant_test.c3t | 318 +++++ test/test_suite2/vector/vector_bit.c3t | 154 +++ test/test_suite2/vector/vector_incdec.c3t | 190 +++ test/test_suite2/vector/vector_init.c3t | 53 + test/test_suite2/vector/vector_ops.c3t | 654 ++++++++++ test/test_suite2/vector/vector_ops2.c3t | 710 ++++++++++ .../vector/vector_to_array_cast.c3t | 38 + test/test_suite2/visibility/ambiguous_var.c3t | 27 + .../visibility/no_shared_imports.c3t | 23 + test/test_suite2/visibility/not_visible.c3t | 16 + test/test_suite2/visibility/private_import.c3 | 21 + test/test_suite2/visibility/private_module.c3 | 17 + test/test_suite2/visibility/shared_module.c3t | 15 + .../visibility/simple_visibility.c3t | 16 + 519 files changed, 26866 insertions(+), 638 deletions(-) rename lib/std/{ => core}/builtin.c3 (88%) rename lib/std/{ => core}/cinterop.c3 (98%) rename lib/std/{ => core}/env.c3 (97%) rename lib/std/{ => core}/mem.c3 (98%) rename lib/std/{ => core}/mem_allocator.c3 (99%) rename lib/std/{ => core}/mem_allocator_fn.c3 (98%) rename lib/std/{ => core}/mem_temp_allocator.c3 (99%) rename lib/std/{ => core}/os/linux.c3 (83%) rename lib/std/{ => core}/os/macos.c3 (81%) rename lib/std/{ => core}/os/windows.c3 (79%) create mode 100644 lib/std/core/str.c3 create mode 100644 lib/std/core/string.c3 create mode 100644 lib/std/core/string_iterator.c3 delete mode 100644 lib/std/str.c3 create mode 100644 test/test_suite/errors/error_else.c3t create mode 100644 test/test_suite/safe/deref.c3t create mode 100644 test/test_suite2/abi/aarch64_args.c3t create mode 100644 test/test_suite2/abi/aarch64_hfa_args.c3t create mode 100644 test/test_suite2/abi/darwin64_avx.c3t create mode 100644 test/test_suite2/abi/darwin64_avx512.c3t create mode 100644 test/test_suite2/abi/darwin64_sse.c3t create mode 100644 test/test_suite2/abi/darwinx64_1.c3t create mode 100644 test/test_suite2/abi/darwinx64_2.c3t create mode 100644 test/test_suite2/abi/literal_load.c3t create mode 100644 test/test_suite2/abi/literal_load_aarch64.c3t create mode 100644 test/test_suite2/abi/literal_load_mingw.c3t create mode 100644 test/test_suite2/abi/macho_section_attributes.c3 create mode 100644 test/test_suite2/abi/pass_large_aarch.c3t create mode 100644 test/test_suite2/abi/regcall_expand.c3t create mode 100644 test/test_suite2/abi/riscv64-lp64-abi.c3t create mode 100644 test/test_suite2/abi/small_struct_x64.c3t create mode 100644 test/test_suite2/abi/sysv_direct_coerce.c3t create mode 100644 test/test_suite2/abi/test_sret.c3t create mode 100644 test/test_suite2/abi/union_x64.c3t create mode 100644 test/test_suite2/abi/vec2_aarch64.c3t create mode 100644 test/test_suite2/abi/vec2_wasm.c3t create mode 100644 test/test_suite2/abi/vec2_x64.c3t create mode 100644 test/test_suite2/abi/x64alignarray.c3t create mode 100644 test/test_suite2/arrays/array_casts.c3t create mode 100644 test/test_suite2/arrays/array_invalid_casts.c3 create mode 100644 test/test_suite2/arrays/array_literal.c3t create mode 100644 test/test_suite2/arrays/array_struct.c3t create mode 100644 test/test_suite2/arrays/complex_array_const.c3t create mode 100644 test/test_suite2/arrays/global_array_non_const.c3 create mode 100644 test/test_suite2/arrays/index_from_back.c3t create mode 100644 test/test_suite2/arrays/index_into_global.c3t create mode 100644 test/test_suite2/arrays/inferred_array_err.c3 create mode 100644 test/test_suite2/arrays/inferred_array_err2.c3 create mode 100644 test/test_suite2/arrays/negative_array.c3 create mode 100644 test/test_suite2/arrays/slice.c3 create mode 100644 test/test_suite2/assert/assert_variants.c3t create mode 100644 test/test_suite2/assert/global_static_assert_not_constant.c3 create mode 100644 test/test_suite2/assert/local_static_assert_not_constant.c3 create mode 100644 test/test_suite2/assert/static_assert.c3 create mode 100644 test/test_suite2/assert/unreachable.c3t create mode 100644 test/test_suite2/assignment/int_assign.c3t create mode 100644 test/test_suite2/attributes/recursive_attributes.c3 create mode 100644 test/test_suite2/attributes/user_defined_attributes.c3t create mode 100644 test/test_suite2/bitstruct/address_of_bitstruct.c3 create mode 100644 test/test_suite2/bitstruct/array_with_boolean.c3t create mode 100644 test/test_suite2/bitstruct/bitfield_access.c3t create mode 100644 test/test_suite2/bitstruct/bitstruct_access_signed.c3t create mode 100644 test/test_suite2/bitstruct/bitstruct_arrays.c3t create mode 100644 test/test_suite2/bitstruct/bitstruct_arrays_be.c3t create mode 100644 test/test_suite2/bitstruct/bitstruct_general.c3 create mode 100644 test/test_suite2/bitstruct/bitstruct_init.c3 create mode 100644 test/test_suite2/bitstruct/bitstruct_intcontainer.c3t create mode 100644 test/test_suite2/bitstruct/bitstruct_overlap.c3 create mode 100644 test/test_suite2/bitstruct/bitstruct_single_error.c3 create mode 100644 test/test_suite2/bitstruct/bitstruct_to_int.c3t create mode 100644 test/test_suite2/bitstruct/embedded_bitstruct.c3t create mode 100644 test/test_suite2/bitstruct/invalid_bitstruct_member_types.c3 create mode 100644 test/test_suite2/bitstruct/invalid_bitstruct_name_other_ident.c3 create mode 100644 test/test_suite2/bitstruct/invalid_bitstruct_type.c3 create mode 100644 test/test_suite2/bitstruct/invalid_empty_struct_union.c3 create mode 100644 test/test_suite2/bitstruct/missing_bitstruct_type.c3 create mode 100644 test/test_suite2/builtins/simple_builtins.c3t create mode 100644 test/test_suite2/cast/cast_from_ptr.c3t create mode 100644 test/test_suite2/cast/cast_ok.c3 create mode 100644 test/test_suite2/cast/cast_parse_fails.c3 create mode 100644 test/test_suite2/cast/cast_parse_fails2.c3 create mode 100644 test/test_suite2/cast/cast_struct.c3 create mode 100644 test/test_suite2/cast/cast_struct_fails.c3 create mode 100644 test/test_suite2/cast/cast_to_failable.c3 create mode 100644 test/test_suite2/cast/top_down_cast_fails.c3 create mode 100644 test/test_suite2/cast/top_down_casts.c3t create mode 100644 test/test_suite2/clang/2002-01_02.c3t create mode 100644 test/test_suite2/clang/2002-03.c3t create mode 100644 test/test_suite2/clang/2002-04.c3t create mode 100644 test/test_suite2/comments/simple_comments.c3 create mode 100644 test/test_suite2/compile_time/compile_time_array.c3t create mode 100644 test/test_suite2/compile_time/compile_time_array_ref.c3t create mode 100644 test/test_suite2/compile_time/compile_time_bitops.c3t create mode 100644 test/test_suite2/compile_time/compile_time_ptr_ref.c3t create mode 100644 test/test_suite2/compile_time/ct_eval.c3t create mode 100644 test/test_suite2/compile_time/ct_for.c3t create mode 100644 test/test_suite2/compile_time/ct_foreach.c3t create mode 100644 test/test_suite2/compile_time/ct_if.c3t create mode 100644 test/test_suite2/compile_time/ct_if_fails.c3 create mode 100644 test/test_suite2/compile_time/ct_switch.c3t create mode 100644 test/test_suite2/compile_time/ct_switch_errors.c3 create mode 100644 test/test_suite2/compile_time/ct_switch_top_level.c3t create mode 100644 test/test_suite2/compile_time/ct_switch_type_check.c3t create mode 100644 test/test_suite2/compile_time/ct_switch_type_errors.c3 create mode 100644 test/test_suite2/compile_time/cttype_reassign.c3t create mode 100644 test/test_suite2/compile_time/not_yet_initialized.c3 create mode 100644 test/test_suite2/compile_time/stringify.c3t create mode 100644 test/test_suite2/compile_time/ternary_folding.c3t create mode 100644 test/test_suite2/compile_time/typeof_example.c3t create mode 100644 test/test_suite2/compile_time/typeof_from_literal.c3 create mode 100644 test/test_suite2/compile_time_introspection/alignof.c3t create mode 100644 test/test_suite2/compile_time_introspection/defined.c3t create mode 100644 test/test_suite2/compile_time_introspection/defined_builtin.c3t create mode 100644 test/test_suite2/compile_time_introspection/defined_err.c3 create mode 100644 test/test_suite2/compile_time_introspection/nameof.c3t create mode 100644 test/test_suite2/compile_time_introspection/nameof_err.c3 create mode 100644 test/test_suite2/compile_time_introspection/offsetof.c3t create mode 100644 test/test_suite2/compile_time_introspection/qnameof.c3t create mode 100644 test/test_suite2/compile_time_introspection/sizeof.c3t create mode 100644 test/test_suite2/compile_time_introspection/sizeof_errors.c3 create mode 100644 test/test_suite2/constants/byte_literal_fail_base64.c3 create mode 100644 test/test_suite2/constants/byte_literal_fail_base64_2.c3 create mode 100644 test/test_suite2/constants/byte_literal_fail_base64_4.c3 create mode 100644 test/test_suite2/constants/byte_literal_fail_hex.c3 create mode 100644 test/test_suite2/constants/byte_literals.c3t create mode 100644 test/test_suite2/constants/char_literals.c3t create mode 100644 test/test_suite2/constants/const_var_copy.c3t create mode 100644 test/test_suite2/constants/constants.c3t create mode 100644 test/test_suite2/contracts/ct_eval_of_ensure.c3 create mode 100644 test/test_suite2/contracts/pure.c3 create mode 100644 test/test_suite2/contracts/pure_calls.c3 create mode 100644 test/test_suite2/contracts/simple_test.c3t create mode 100644 test/test_suite2/debug_symbols/constants.c3t create mode 100644 test/test_suite2/defer/defer_and_expr_block.c3t create mode 100644 test/test_suite2/defer/defer_single_stmt.c3 create mode 100644 test/test_suite2/defer/defer_static_var.c3t create mode 100644 test/test_suite2/defer/defer_with_rethrow.c3 create mode 100644 test/test_suite2/defer/defer_with_return.c3 create mode 100644 test/test_suite2/define/common.c3 create mode 100644 test/test_suite2/define/define_name_errors.c3 create mode 100644 test/test_suite2/define/forbidden_defines.c3 create mode 100644 test/test_suite2/distinct/distinct_invalid.c3 create mode 100644 test/test_suite2/distinct/distinct_struct.c3 create mode 100644 test/test_suite2/distinct/distinct_struct_array.c3 create mode 100644 test/test_suite2/distinct/distinct_union.c3 create mode 100644 test/test_suite2/distinct/test_errors.c3 create mode 100644 test/test_suite2/distinct/test_ops_on_int.c3 create mode 100644 test/test_suite2/distinct/test_ops_on_struct.c3 create mode 100644 test/test_suite2/enumerations/compile_time.c3t create mode 100644 test/test_suite2/enumerations/enum_associated_value.c3t create mode 100644 test/test_suite2/enumerations/enum_cast.c3t create mode 100644 test/test_suite2/enumerations/enum_values.c3t create mode 100644 test/test_suite2/enumerations/simple_inference.c3t create mode 100644 test/test_suite2/errors/anyerr_void.c3t create mode 100644 test/test_suite2/errors/bitshift_failable.c3 create mode 100644 test/test_suite2/errors/else_checks.c3t create mode 100644 test/test_suite2/errors/error_decl_ok.c3 create mode 100644 test/test_suite2/errors/error_else.c3t create mode 100644 test/test_suite2/errors/error_regression_2.c3t create mode 100644 test/test_suite2/errors/error_semantic_fails.c3 create mode 100644 test/test_suite2/errors/error_throw.c3 create mode 100644 test/test_suite2/errors/error_union.c3 create mode 100644 test/test_suite2/errors/failable_inits.c3t create mode 100644 test/test_suite2/errors/failable_taddr_and_access.c3t create mode 100644 test/test_suite2/errors/failable_untyped_list.c3 create mode 100644 test/test_suite2/errors/general_error_regression.c3t create mode 100644 test/test_suite2/errors/illegal_use_of_failable.c3 create mode 100644 test/test_suite2/errors/macro_err.c3t create mode 100644 test/test_suite2/errors/macro_err2.c3t create mode 100644 test/test_suite2/errors/macro_err3.c3t create mode 100644 test/test_suite2/errors/no_common.c3 create mode 100644 test/test_suite2/errors/or_err_bool.c3t create mode 100644 test/test_suite2/errors/precedence_err.c3 create mode 100644 test/test_suite2/errors/rethrow.c3t create mode 100644 test/test_suite2/errors/rethrow_mingw.c3t create mode 100644 test/test_suite2/errors/rethrow_no_err.c3 create mode 100644 test/test_suite2/errors/simple_static_failable.c3t create mode 100644 test/test_suite2/errors/try_assign.c3t create mode 100644 test/test_suite2/errors/try_catch_if.c3t create mode 100644 test/test_suite2/errors/try_catch_unwrapping_while_if.c3 create mode 100644 test/test_suite2/errors/try_unwrap_using_assert.c3t create mode 100644 test/test_suite2/errors/try_with_assign_to_failable.c3 create mode 100644 test/test_suite2/errors/try_with_chained_unwrap.c3t create mode 100644 test/test_suite2/errors/try_with_chained_unwrap_errors.c3 create mode 100644 test/test_suite2/errors/try_with_unwrap.c3t create mode 100644 test/test_suite2/errors/try_with_unwrapper.c3t create mode 100644 test/test_suite2/errors/try_with_weird_stuff.c3 create mode 100644 test/test_suite2/examples/gameoflife.c3 create mode 100644 test/test_suite2/expression_block/expression_block_break.c3 create mode 100644 test/test_suite2/expressions/addr_compiles.c3t create mode 100644 test/test_suite2/expressions/addr_of_fails.c3 create mode 100644 test/test_suite2/expressions/arithmetics.c3 create mode 100644 test/test_suite2/expressions/arithmetics_sema_fail.c3 create mode 100644 test/test_suite2/expressions/assign.c3 create mode 100644 test/test_suite2/expressions/assignability.c3 create mode 100644 test/test_suite2/expressions/assignment_precedence.c3t create mode 100644 test/test_suite2/expressions/call_arg_types.c3 create mode 100644 test/test_suite2/expressions/call_inline.c3t create mode 100644 test/test_suite2/expressions/casts/cast_const.c3 create mode 100644 test/test_suite2/expressions/casts/cast_enum_to_various.c3 create mode 100644 test/test_suite2/expressions/casts/cast_expr.c3t create mode 100644 test/test_suite2/expressions/casts/cast_failable.c3 create mode 100644 test/test_suite2/expressions/casts/cast_func_to_various.c3 create mode 100644 test/test_suite2/expressions/casts/cast_to_nonscalar.c3 create mode 100644 test/test_suite2/expressions/casts/cast_unknown.c3 create mode 100644 test/test_suite2/expressions/casts/explicit_cast.c3 create mode 100644 test/test_suite2/expressions/casts/narrowing.c3 create mode 100644 test/test_suite2/expressions/chained_conditional.c3t create mode 100644 test/test_suite2/expressions/check_implict_conversion_signed_unsigned.c3t create mode 100644 test/test_suite2/expressions/elvis.c3t create mode 100644 test/test_suite2/expressions/fail_index_usize.c3 create mode 100644 test/test_suite2/expressions/folding_ptr.c3t create mode 100644 test/test_suite2/expressions/incdec.c3t create mode 100644 test/test_suite2/expressions/negate_int.c3 create mode 100644 test/test_suite2/expressions/no_valid_conversion_minus.c3 create mode 100644 test/test_suite2/expressions/parsed_numbers.c3t create mode 100644 test/test_suite2/expressions/pointer_access.c3t create mode 100644 test/test_suite2/expressions/pointer_arith.c3 create mode 100644 test/test_suite2/expressions/pointer_conv_error.c3 create mode 100644 test/test_suite2/expressions/pointer_to_bool.c3 create mode 100644 test/test_suite2/expressions/rvalues.c3 create mode 100644 test/test_suite2/expressions/simple_float_sub_neg.c3t create mode 100644 test/test_suite2/expressions/strings.c3t create mode 100644 test/test_suite2/expressions/ternary_bool.c3t create mode 100644 test/test_suite2/expressions/ternary_no_ident.c3 create mode 100644 test/test_suite2/expressions/unsafe_comparisons.c3 create mode 100644 test/test_suite2/failable_catch.c3t create mode 100644 test/test_suite2/floats/convert_float.c3t create mode 100644 test/test_suite2/floats/explicit_float_truncation_needed.c3 create mode 100644 test/test_suite2/floats/float_exceeding_size.c3 create mode 100644 test/test_suite2/floats/inf_nan.c3t create mode 100644 test/test_suite2/from_docs/examples_defer.c3t create mode 100644 test/test_suite2/from_docs/examples_forswitch.c3t create mode 100644 test/test_suite2/from_docs/examples_functionpointer.c3t create mode 100644 test/test_suite2/from_docs/examples_if_catch.c3t create mode 100644 test/test_suite2/from_docs/examples_macro_function.c3t create mode 100644 test/test_suite2/from_docs/examples_struct.c3 create mode 100644 test/test_suite2/functions/assorted_tests.c3t create mode 100644 test/test_suite2/functions/body_argument_fail.c3 create mode 100644 test/test_suite2/functions/default_param_fail.c3 create mode 100644 test/test_suite2/functions/double_return.c3t create mode 100644 test/test_suite2/functions/macro_arguments.c3 create mode 100644 test/test_suite2/functions/missing_first_paren.c3 create mode 100644 test/test_suite2/functions/missing_return.c3 create mode 100644 test/test_suite2/functions/naked_function.c3t create mode 100644 test/test_suite2/functions/naked_function_fail.c3 create mode 100644 test/test_suite2/functions/returning_void.c3t create mode 100644 test/test_suite2/functions/splat.c3t create mode 100644 test/test_suite2/functions/splat_aarch64.c3t create mode 100644 test/test_suite2/functions/splat_mingw.c3t create mode 100644 test/test_suite2/functions/static_vars.c3t create mode 100644 test/test_suite2/functions/test_regression.c3t create mode 100644 test/test_suite2/functions/test_regression_mingw.c3t create mode 100644 test/test_suite2/functions/typeless_varargs.c3t create mode 100644 test/test_suite2/functions/vararg_argument_fails.c3 create mode 100644 test/test_suite2/functions/varargs.c3t create mode 100644 test/test_suite2/generic/generic_copy.c3t create mode 100644 test/test_suite2/generic/generic_idents.c3t create mode 100644 test/test_suite2/globals/external_global.c3t create mode 100644 test/test_suite2/globals/global_align.c3t create mode 100644 test/test_suite2/globals/global_extname.c3t create mode 100644 test/test_suite2/globals/global_init.c3 create mode 100644 test/test_suite2/globals/misplaced_const.c3 create mode 100644 test/test_suite2/globals/recursive_globals.c3 create mode 100644 test/test_suite2/globals/recursive_locals.c3 create mode 100644 test/test_suite2/globals/self_referencing_local.c3 create mode 100644 test/test_suite2/globals/static_global.c3 create mode 100644 test/test_suite2/import/access_other_module.c3t create mode 100644 test/test_suite2/import/autoimport.c3 create mode 100644 test/test_suite2/import/import_error.c3 create mode 100644 test/test_suite2/import/import_error_multi.c3 create mode 100644 test/test_suite2/import/import_error_out_of_order.c3 create mode 100644 test/test_suite2/import/import_error_string.c3 create mode 100644 test/test_suite2/import/import_implicit.c3 create mode 100644 test/test_suite2/import/import_works.c3t create mode 100644 test/test_suite2/initializer_lists/disallowed_lists.c3 create mode 100644 test/test_suite2/initializer_lists/fasta.c3t create mode 100644 test/test_suite2/initializer_lists/general_tests.c3t create mode 100644 test/test_suite2/initializer_lists/indexing_into_complist.c3 create mode 100644 test/test_suite2/initializer_lists/ranges_to_dynamic.c3t create mode 100644 test/test_suite2/initializer_lists/statics.c3t create mode 100644 test/test_suite2/initializer_lists/subarrays.c3t create mode 100644 test/test_suite2/initializer_lists/zero_init.c3t create mode 100644 test/test_suite2/lexing/expected_directive.c3 create mode 100644 test/test_suite2/lexing/invalid_hex_in_hexarray.c3 create mode 100644 test/test_suite2/lexing/invalid_hex_in_hexarray2.c3 create mode 100644 test/test_suite2/lexing/no_builtin.c3 create mode 100644 test/test_suite2/literals/bad_bitwidth.c3 create mode 100644 test/test_suite2/literals/literal_general.c3t create mode 100644 test/test_suite2/literals/multi_unicode.c3 create mode 100644 test/test_suite2/literals/radix_numbers_errors.c3 create mode 100644 test/test_suite2/literals/too_small.c3 create mode 100644 test/test_suite2/macro_methods/access.c3 create mode 100644 test/test_suite2/macro_methods/macro_method_fails.c3 create mode 100644 test/test_suite2/macro_methods/macro_methods_defined_twice.c3 create mode 100644 test/test_suite2/macros/hash_ident.c3 create mode 100644 test/test_suite2/macros/macro_body_as_value.c3 create mode 100644 test/test_suite2/macros/macro_body_defer.c3t create mode 100644 test/test_suite2/macros/macro_body_errors.c3 create mode 100644 test/test_suite2/macros/macro_calls_prefix.c3 create mode 100644 test/test_suite2/macros/macro_common.c3t create mode 100644 test/test_suite2/macros/macro_convert_literal.c3 create mode 100644 test/test_suite2/macros/macro_defer_exit.c3t create mode 100644 test/test_suite2/macros/macro_defer_scope.c3t create mode 100644 test/test_suite2/macros/macro_defer_with_body.c3t create mode 100644 test/test_suite2/macros/macro_import_res_private.c3t create mode 100644 test/test_suite2/macros/macro_import_resolution.c3 create mode 100644 test/test_suite2/macros/macro_nested_labels.c3t create mode 100644 test/test_suite2/macros/macro_resolution.c3 create mode 100644 test/test_suite2/macros/macro_rtype.c3 create mode 100644 test/test_suite2/macros/macro_with_body.c3t create mode 100644 test/test_suite2/macros/no_body.c3 create mode 100644 test/test_suite2/macros/type_params.c3t create mode 100644 test/test_suite2/macros/userland_bitcast.c3t create mode 100644 test/test_suite2/methods/access.c3 create mode 100644 test/test_suite2/methods/enum_distinct_err_methods.c3t create mode 100644 test/test_suite2/methods/extension_method.c3t create mode 100644 test/test_suite2/methods/extension_method_already_exist.c3 create mode 100644 test/test_suite2/methods/methods_defined_twice.c3 create mode 100644 test/test_suite2/module/missing_semi.c3 create mode 100644 test/test_suite2/module/module_bad_path_ident.c3 create mode 100644 test/test_suite2/module/module_bad_path_invalid.c3 create mode 100644 test/test_suite2/module/module_bad_path_keyword.c3 create mode 100644 test/test_suite2/module/module_error_string.c3 create mode 100644 test/test_suite2/module/module_start_bad_ident.c3 create mode 100644 test/test_suite2/module/module_start_invalid.c3 create mode 100644 test/test_suite2/module/module_start_keyword.c3 create mode 100644 test/test_suite2/module/private_module.c3 create mode 100644 test/test_suite2/module/unknown_modules.c3 create mode 100644 test/test_suite2/pointers/array_pointer_decay.c3t create mode 100644 test/test_suite2/pointers/const_pointer.c3t create mode 100644 test/test_suite2/pointers/pointer_index.c3t create mode 100644 test/test_suite2/pointers/subarray_variant_to_ptr.c3t create mode 100644 test/test_suite2/precedence/required_parens.c3 create mode 100644 test/test_suite2/regression/crash_on_right_paren_macro.c3 create mode 100644 test/test_suite2/safe/deref.c3t create mode 100644 test/test_suite2/slices/slice_assign.c3t create mode 100644 test/test_suite2/statements/binary_fail.c3 create mode 100644 test/test_suite2/statements/call_missing_paren.c3 create mode 100644 test/test_suite2/statements/comparison_widening.c3t create mode 100644 test/test_suite2/statements/conditional_return.c3 create mode 100644 test/test_suite2/statements/custom_foreach_with_ref.c3t create mode 100644 test/test_suite2/statements/default_args.c3 create mode 100644 test/test_suite2/statements/defer_break.c3t create mode 100644 test/test_suite2/statements/defer_break_simple.c3t create mode 100644 test/test_suite2/statements/defer_break_switch.c3t create mode 100644 test/test_suite2/statements/defer_do_while.c3t create mode 100644 test/test_suite2/statements/defer_in_block.c3t create mode 100644 test/test_suite2/statements/defer_in_defer.c3t create mode 100644 test/test_suite2/statements/defer_in_defer2.c3t create mode 100644 test/test_suite2/statements/defer_next_switch.c3t create mode 100644 test/test_suite2/statements/defer_return.c3t create mode 100644 test/test_suite2/statements/defer_test.c3 create mode 100644 test/test_suite2/statements/defer_with_loop.c3t create mode 100644 test/test_suite2/statements/do_without_compound.c3 create mode 100644 test/test_suite2/statements/fallthough_do.c3t create mode 100644 test/test_suite2/statements/for.c3 create mode 100644 test/test_suite2/statements/for_empty.c3 create mode 100644 test/test_suite2/statements/for_errors.c3 create mode 100644 test/test_suite2/statements/for_with_extra_declarations.c3 create mode 100644 test/test_suite2/statements/foreach_break.c3t create mode 100644 test/test_suite2/statements/foreach_common.c3t create mode 100644 test/test_suite2/statements/foreach_custom.c3t create mode 100644 test/test_suite2/statements/foreach_custom_errors.c3 create mode 100644 test/test_suite2/statements/foreach_custom_macro.c3t create mode 100644 test/test_suite2/statements/foreach_errors.c3 create mode 100644 test/test_suite2/statements/foreach_parse_error.c3 create mode 100644 test/test_suite2/statements/foreach_with_error.c3 create mode 100644 test/test_suite2/statements/if_decl.c3 create mode 100644 test/test_suite2/statements/if_single.c3 create mode 100644 test/test_suite2/statements/if_tests.c3t create mode 100644 test/test_suite2/statements/if_while_do_error.c3 create mode 100644 test/test_suite2/statements/label_errors.c3 create mode 100644 test/test_suite2/statements/labelled_continue_for.c3t create mode 100644 test/test_suite2/statements/ranged_switch.c3t create mode 100644 test/test_suite2/statements/return_stmt.c3 create mode 100644 test/test_suite2/statements/return_switch.c3t create mode 100644 test/test_suite2/statements/return_with_other_at_end.c3 create mode 100644 test/test_suite2/statements/simple_do.c3t create mode 100644 test/test_suite2/statements/switch_error_range.c3 create mode 100644 test/test_suite2/statements/switch_errors.c3 create mode 100644 test/test_suite2/statements/various_switching.c3t create mode 100644 test/test_suite2/statements/while_statement_placement.c3 create mode 100644 test/test_suite2/statements/while_switch.c3t create mode 100644 test/test_suite2/strings/literal_errors.c3 create mode 100644 test/test_suite2/strings/literal_hex_ok.c3 create mode 100644 test/test_suite2/strings/literal_to_subarray.c3t create mode 100644 test/test_suite2/strings/multiline_strings.c3t create mode 100644 test/test_suite2/strings/string_escape.c3t create mode 100644 test/test_suite2/strings/string_len.c3t create mode 100644 test/test_suite2/strings/string_to_array.c3t create mode 100644 test/test_suite2/struct/duplicate_member.c3 create mode 100644 test/test_suite2/struct/flex_array_struct_err.c3 create mode 100644 test/test_suite2/struct/func_return_struct.c3 create mode 100644 test/test_suite2/struct/member_access.c3 create mode 100644 test/test_suite2/struct/member_expr.c3 create mode 100644 test/test_suite2/struct/recursive_structs.c3 create mode 100644 test/test_suite2/struct/simple_struct.c3t create mode 100644 test/test_suite2/struct/struct_as_value.c3t create mode 100644 test/test_suite2/struct/struct_as_value_aarch64.c3t create mode 100644 test/test_suite2/struct/struct_codegen.c3t create mode 100644 test/test_suite2/struct/struct_codegen_empty.c3t create mode 100644 test/test_suite2/struct/struct_codegen_fam.c3t create mode 100644 test/test_suite2/struct/struct_const_construct_simple.c3t create mode 100644 test/test_suite2/struct/struct_pack_and_align.c3t create mode 100644 test/test_suite2/struct/struct_params.c3 create mode 100644 test/test_suite2/struct/zero_member.c3 create mode 100644 test/test_suite2/subarrays/slice_comparison.c3t create mode 100644 test/test_suite2/subarrays/slice_negative_len.c3 create mode 100644 test/test_suite2/subarrays/slice_offset.c3t create mode 100644 test/test_suite2/subarrays/slice_offset_neg_end.c3t create mode 100644 test/test_suite2/subarrays/slice_offset_neg_start.c3t create mode 100644 test/test_suite2/subarrays/slice_start.c3t create mode 100644 test/test_suite2/subarrays/slice_syntax.c3 create mode 100644 test/test_suite2/subarrays/sub_array_init.c3 create mode 100644 test/test_suite2/switch/failable_switch.c3 create mode 100644 test/test_suite2/symbols/allow_local_shadowing.c3 create mode 100644 test/test_suite2/symbols/shadow_struct.c3 create mode 100644 test/test_suite2/symbols/various.c3 create mode 100644 test/test_suite2/types/enum_illegal_type.c3 create mode 100644 test/test_suite2/types/enum_implicit_overflow.c3 create mode 100644 test/test_suite2/types/enum_inference.c3 create mode 100644 test/test_suite2/types/enum_ok.c3 create mode 100644 test/test_suite2/types/enum_param.c3 create mode 100644 test/test_suite2/types/enum_parse_errors.c3 create mode 100644 test/test_suite2/types/recursive_array.c3 create mode 100644 test/test_suite2/types/recursive_typedef.c3 create mode 100644 test/test_suite2/types/redefinition.c3 create mode 100644 test/test_suite2/types/typedefs.c3 create mode 100644 test/test_suite2/types/various.c3 create mode 100644 test/test_suite2/unicode/commenting-out.c3 create mode 100644 test/test_suite2/union/flexible_array_union.c3 create mode 100644 test/test_suite2/union/test_unions.c3 create mode 100644 test/test_suite2/union/union_codegen_const.c3t create mode 100644 test/test_suite2/union/union_codegen_empty.c3t create mode 100644 test/test_suite2/union/union_codegen_overwrite_call.c3t create mode 100644 test/test_suite2/union/union_in_struct.c3t create mode 100644 test/test_suite2/union/union_member_voidcast.c3 create mode 100644 test/test_suite2/variables/consts.c3 create mode 100644 test/test_suite2/variant/variant_assign.c3t create mode 100644 test/test_suite2/variant/variant_switch.c3t create mode 100644 test/test_suite2/variant/variant_test.c3t create mode 100644 test/test_suite2/vector/vector_bit.c3t create mode 100644 test/test_suite2/vector/vector_incdec.c3t create mode 100644 test/test_suite2/vector/vector_init.c3t create mode 100644 test/test_suite2/vector/vector_ops.c3t create mode 100644 test/test_suite2/vector/vector_ops2.c3t create mode 100644 test/test_suite2/vector/vector_to_array_cast.c3t create mode 100644 test/test_suite2/visibility/ambiguous_var.c3t create mode 100644 test/test_suite2/visibility/no_shared_imports.c3t create mode 100644 test/test_suite2/visibility/not_visible.c3t create mode 100644 test/test_suite2/visibility/private_import.c3 create mode 100644 test/test_suite2/visibility/private_module.c3 create mode 100644 test/test_suite2/visibility/shared_module.c3t create mode 100644 test/test_suite2/visibility/simple_visibility.c3t diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0ca9ed26c..c73fea6ad 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -159,7 +159,11 @@ jobs: - name: run compiler tests run: | cd test - python3 src/tester.py ../build/c3c test_suite/ + if [[ "${{matrix.llvm_version}}" < 15 ]]; then + python3 src/tester.py ../build/c3c test_suite/ + else + python3 src/tester.py ../build/c3c test_suite2/ + fi build-mac: runs-on: macos-latest @@ -168,7 +172,7 @@ jobs: fail-fast: false matrix: build_type: [Release, Debug] - llvm_version: [12, 13] + llvm_version: [12, 13, 14] steps: - uses: actions/checkout@v3 - name: Download LLVM diff --git a/CMakeLists.txt b/CMakeLists.txt index ff0f358b4..605a4fb34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,9 +8,14 @@ set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3") +#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1 -fsanitize=undefined") +#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O1 -fsanitize=undefined") +#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3 -fsanitize=undefined") +#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3 -fsanitize=undefined") +#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined") option(C3_USE_TB "Enable TB" OFF) set(C3_LLVM_VERSION "auto" CACHE STRING "Use LLVM version [default: auto]") diff --git a/lib/std/array.c3 b/lib/std/array.c3 index 2b8b3fb89..558444cef 100644 --- a/lib/std/array.c3 +++ b/lib/std/array.c3 @@ -2,7 +2,6 @@ // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::array; -import std::mem; /** * @require elements > 0 diff --git a/lib/std/builtin.c3 b/lib/std/core/builtin.c3 similarity index 88% rename from lib/std/builtin.c3 rename to lib/std/core/builtin.c3 index 590d65739..3793dfac1 100644 --- a/lib/std/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -1,9 +1,14 @@ // Copyright (c) 2021 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::builtin; +module std::core::builtin; import libc; +fault IteratorResult +{ + NO_MORE_ELEMENT +} + fault VarCastResult { TYPE_MISMATCH @@ -76,6 +81,29 @@ macro unreachable($string = "Unreachable statement reached.") @autoimport @noret $$unreachable(); } +enum TypeKind : char +{ + VOID, // 0 + BOOL, // 1 + FLOAT, // 2 + INTEGER,// 3 + STRUCT, // 4 + UNION, // 5 + ENUM, // 6 + FAULT, // 7 + ARRAY, + POINTER, + VAR_ARRAY, + SUBARRAY, + OPAQUE + // ALIAS, +} + +struct TypeEnum +{ + TypeKind type; + usize elements; +} /* enum TypeKind { diff --git a/lib/std/cinterop.c3 b/lib/std/core/cinterop.c3 similarity index 98% rename from lib/std/cinterop.c3 rename to lib/std/core/cinterop.c3 index 693b1d45e..1fc6c2cc3 100644 --- a/lib/std/cinterop.c3 +++ b/lib/std/core/cinterop.c3 @@ -1,7 +1,7 @@ // Copyright (c) 2021 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::cinterop; +module std::core::cinterop; const C_INT_SIZE = $$C_INT_SIZE; const C_LONG_SIZE = $$C_LONG_SIZE; diff --git a/lib/std/env.c3 b/lib/std/core/env.c3 similarity index 97% rename from lib/std/env.c3 rename to lib/std/core/env.c3 index af1cd02db..5c675069a 100644 --- a/lib/std/env.c3 +++ b/lib/std/core/env.c3 @@ -1,7 +1,7 @@ // Copyright (c) 2021 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::env; +module std::core::env; enum CompilerOptLevel { diff --git a/lib/std/mem.c3 b/lib/std/core/mem.c3 similarity index 98% rename from lib/std/mem.c3 rename to lib/std/core/mem.c3 index 6ebc0197f..c5d45dd42 100644 --- a/lib/std/mem.c3 +++ b/lib/std/core/mem.c3 @@ -1,7 +1,7 @@ // Copyright (c) 2021 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::mem; +module std::core::mem; macro @volatile_load(&x) { @@ -77,6 +77,11 @@ fault AllocationFailure private tlocal Allocator thread_allocator = { null, SYSTEM_ALLOCATOR }; +macro Allocator current_allocator() +{ + return thread_allocator; +} + struct Allocator { void* data; diff --git a/lib/std/mem_allocator.c3 b/lib/std/core/mem_allocator.c3 similarity index 99% rename from lib/std/mem_allocator.c3 rename to lib/std/core/mem_allocator.c3 index 1c827b971..f1cf06600 100644 --- a/lib/std/mem_allocator.c3 +++ b/lib/std/core/mem_allocator.c3 @@ -1,4 +1,4 @@ -module std::mem; +module std::core::mem; define AllocatorFunction = fn void*!(void* alloc_data, usize new_size, usize alignment, void* old_pointer, AllocationKind kind); diff --git a/lib/std/mem_allocator_fn.c3 b/lib/std/core/mem_allocator_fn.c3 similarity index 98% rename from lib/std/mem_allocator_fn.c3 rename to lib/std/core/mem_allocator_fn.c3 index 0fa2750e2..8e9f83872 100644 --- a/lib/std/mem_allocator_fn.c3 +++ b/lib/std/core/mem_allocator_fn.c3 @@ -1,4 +1,4 @@ -module std::mem; +module std::core::mem; import libc; private fn void*! null_allocator_fn(void *data, usize bytes, usize alignment, void* old_pointer, AllocationKind kind) diff --git a/lib/std/mem_temp_allocator.c3 b/lib/std/core/mem_temp_allocator.c3 similarity index 99% rename from lib/std/mem_temp_allocator.c3 rename to lib/std/core/mem_temp_allocator.c3 index bf7101d7f..01bfd6bac 100644 --- a/lib/std/mem_temp_allocator.c3 +++ b/lib/std/core/mem_temp_allocator.c3 @@ -1,4 +1,4 @@ -module std::mem; +module std::core::mem; const TEMP_BLOCK_SIZE = 1024; const TEMP_PAGES = 64; diff --git a/lib/std/os/linux.c3 b/lib/std/core/os/linux.c3 similarity index 83% rename from lib/std/os/linux.c3 rename to lib/std/core/os/linux.c3 index 1e738a329..93db894d4 100644 --- a/lib/std/os/linux.c3 +++ b/lib/std/core/os/linux.c3 @@ -1,5 +1,4 @@ -module std::os::linux; -import std::env; +module std::core::os::linux; $if (env::OS_TYPE == OsType.LINUX): diff --git a/lib/std/os/macos.c3 b/lib/std/core/os/macos.c3 similarity index 81% rename from lib/std/os/macos.c3 rename to lib/std/core/os/macos.c3 index 5bea3eddd..b1f672dc1 100644 --- a/lib/std/os/macos.c3 +++ b/lib/std/core/os/macos.c3 @@ -1,6 +1,4 @@ -module std::os::macos; -import std::env; - +module std::core::os::macos; $if (env::OS_TYPE == OsType.MACOSX): extern fn int* __error(); diff --git a/lib/std/os/windows.c3 b/lib/std/core/os/windows.c3 similarity index 79% rename from lib/std/os/windows.c3 rename to lib/std/core/os/windows.c3 index d634ed918..0a89ba7c4 100644 --- a/lib/std/os/windows.c3 +++ b/lib/std/core/os/windows.c3 @@ -1,5 +1,4 @@ -module std::os::windows; -import std::env; +module std::core::os::windows; $if (env::OS_TYPE == OsType.WIN32): diff --git a/lib/std/core/str.c3 b/lib/std/core/str.c3 new file mode 100644 index 000000000..00ede7efe --- /dev/null +++ b/lib/std/core/str.c3 @@ -0,0 +1,166 @@ +module std::core::str; + + +define ZString = distinct char*; +define Char32 = uint; + +fn String join(char[][] s, char[] joiner) +{ + if (!s.len) return (String)null; + usize total_size = joiner.len * s.len; + foreach (char[]* &str : s) + { + total_size += str.len; + } + String res = string::new_with_capacity(total_size); + res.append(s[0]); + foreach (char[]* &str : s[1..]) + { + res.append(joiner); + res.append(*str); + } + return res; +} + + +fn ZString copy_zstring(char[] s) +{ + usize len = s.len; + char* str = mem::alloc(len + 1); + mem::copy(str, s.ptr, len); + str[len] = 0; + return (ZString)str; +} + +fn ZString tcopy_zstring(char[] s) +{ + usize len = s.len; + char* str = mem::talloc(len + 1)!!; + mem::copy(str, s.ptr, len); + str[len] = 0; + return (ZString)str; +} + +fault UnicodeResult +{ + INVALID_UTF8 +} + +fn Char32! utf8CharTo32(char* ptr, int* size) +{ + int max_size = *size; + if (max_size < 1) return UnicodeResult.INVALID_UTF8!; + char c = (ptr++)[0]; + + if ((c & 0x80) == 0) + { + *size = 1; + return c; + } + if ((c & 0xE0) == 0xC0) + { + if (max_size < 2) return UnicodeResult.INVALID_UTF8!; + *size = 2; + Char32 uc = (c & 0x1F) << 6; + c = *ptr; + if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!; + return uc + c & 0x3F; + } + if ((c & 0xF0) == 0xE0) + { + if (max_size < 3) return UnicodeResult.INVALID_UTF8!; + *size = 3; + Char32 uc = (c & 0x0F) << 12; + c = ptr++[0]; + if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!; + uc += (c & 0x3F) << 6; + c = ptr++[0]; + if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!; + return uc + c & 0x3F; + } + if (max_size < 4) return UnicodeResult.INVALID_UTF8!; + *size = 4; + Char32 uc = (c & 0x07) << 18; + c = ptr++[0]; + if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!; + uc += (c & 0x3F) << 12; + c = ptr++[0]; + if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!; + uc += (c & 0x3F) << 6; + c = ptr++[0]; + if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!; + return uc + c & 0x3F; +} + +fn usize utf8_codepoints(char[] utf8) +{ + usize len = 0; + foreach (char c : utf8) + { + if (c & 0xC0 != 0x80) len++; + } + return len; +} + +fn Char32[]! utf8to32(char[] utf8, Allocator allocator = { null, null }) +{ + if (!allocator.function) allocator = mem::current_allocator(); + usize len = utf8.len; + Char32* data = allocator.alloc((len + 1) * Char32.sizeof)?; + usize len32 = 0; + for (usize i = 0; i < len;) + { + int width = (int)min(len - i, 4); + Char32 uc = utf8CharTo32(&utf8[i], &width) @inline?; + i += width; + data[len32++] = uc; + } + return data[0 .. len32 - 1]; +} + +fn char[] copy(char[] s) +{ + usize len = s.len; + ZString str_copy = copy_zstring(s) @inline; + return str_copy[..len]; +} + +fn char[] tcopy(char[] s) +{ + usize len = s.len; + ZString str_copy = tcopy_zstring(s) @inline; + return str_copy[..len]; +} + +fn char[] tconcat(char[] s1, char[] s2) +{ + usize full_len = s1.len + s2.len; + char* str = mem::talloc(full_len + 1)!!; + usize s1_len = s1.len; + mem::copy(str, s1.ptr, s1_len); + mem::copy(str + s1_len, s2.ptr, s2.len); + str[full_len] = 0; + return str[..full_len]; +} + +fn char[] concat(char[] s1, char[] s2) +{ + usize full_len = s1.len + s2.len; + char* str = mem::alloc(full_len + 1); + usize s1_len = s1.len; + mem::copy(str, s1.ptr, s1_len); + mem::copy(str + s1_len, s2.ptr, s2.len); + str[full_len] = 0; + return str[..full_len]; +} + +fn usize ZString.len(ZString *str) +{ + usize len = 0; + char* ptr = (char*)*str; + while (char c = ptr++[0]) + { + if (c & 0xC0 != 0x80) len++; + } + return len; +} \ No newline at end of file diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 new file mode 100644 index 000000000..b1d417fda --- /dev/null +++ b/lib/std/core/string.c3 @@ -0,0 +1,255 @@ +module std::core::string; +import libc; + +define String = distinct void*; + +private struct StringData +{ + Allocator allocator; + usize len; + usize capacity; + char[*] chars; +} + +const usize MIN_CAPACITY = 16; + +fn String new_with_capacity(usize capacity, Allocator allocator = { null, null }) +{ + if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY; + if (!allocator.function) + { + allocator = mem::current_allocator(); + } + assert(allocator.function, "Expected an allocator to be present."); + StringData* data = allocator.alloc(StringData.sizeof + capacity)!!; + data.allocator = allocator; + data.len = 0; + data.capacity = capacity; + return (String)data; +} + +fn String new(char[] c) +{ + usize len = c.len; + String str = new_with_capacity(len); + StringData* data = str.data(); + if (len) + { + data.len = len; + mem::copy(&data.chars, c.ptr, len); + } + return (String)data; +} + +fn ZString String.zstr(String* str) +{ + StringData* data = str.data(); + if (!str) return (ZString)""; + if (data.capacity == data.len) + { + libc::printf("feofk\n"); + str.reserve(1); + data.chars[data.len] = 0; + } + else if (data.chars[data.len] != 0) + { + data.chars[data.len] = 0; + } + return (ZString)&data.chars[0]; +} + +fn usize String.len(String* this) +{ + if (!*this) return 0; + return this.data().len; +} +/** + * @require new_size <= this.len() + */ +fn void String.chop(String* this, usize new_size) +{ + if (!*this) return; + this.data().len = new_size; +} + +fn char[] String.str(String* str) +{ + StringData* data = (StringData*)*str; + return data.chars[0..data.len - 1]; +} + +fn void String.append_utf32(String* str, Char32[] chars) +{ + str.reserve(chars.len); + foreach (Char32 c : chars) + { + str.append_char32(c); + } +} + +/** + * @require c < 0x10ffff + */ +fn void String.append_char32(String* str, Char32 c) +{ + if (c < 0x7f) + { + str.reserve(1); + StringData* data = str.data(); + data.chars[data.len++] = (char)c; + return; + } + if (c < 0x7ff) + { + str.reserve(2); + StringData* data = str.data(); + data.chars[data.len++] = (char)(0xC0 | c >> 6); + data.chars[data.len++] = (char)(0x80 | (c & 0x3F)); + return; + } + if (c < 0xffff) + { + str.reserve(3); + StringData* data = str.data(); + data.chars[data.len++] = (char)(0xE0 | c >> 12); + data.chars[data.len++] = (char)(0x80 | (c >> 6 & 0x3F)); + data.chars[data.len++] = (char)(0x80 | (c & 0x3F)); + return; + } + str.reserve(4); + StringData* data = str.data(); + data.chars[data.len++] = (char)(0xF0 | c >> 18); + data.chars[data.len++] = (char)(0x80 | (c >> 12 & 0x3F)); + data.chars[data.len++] = (char)(0x80 | (c >> 6 & 0x3F)); + data.chars[data.len++] = (char)(0x80 | (c & 0x3F)); +} + +fn String String.copy(String* str, Allocator allocator = { null, null }) +{ + if (!*str) + { + if (allocator.function) return new_with_capacity(0, allocator); + return (String)null; + } + if (!allocator.function) allocator = mem::current_allocator(); + StringData* data = str.data(); + String new_string = new_with_capacity(data.capacity, allocator); + mem::copy((char*)new_string.data(), (char*)data, StringData.sizeof + data.len); + return new_string; +} + +fn ZString String.copy_zstr(String* str, Allocator allocator = { null, null }) +{ + usize str_len = str.len(); + if (!str_len) + { + if (allocator.function) return (ZString)allocator.calloc(1, 1)!!; + return (ZString)mem::calloc(1, 1); + } + if (!allocator.function) allocator = mem::current_allocator(); + char* zstr = allocator.alloc(str_len + 1)!!; + StringData* data = str.data(); + mem::copy(zstr, &data.chars, str_len); + zstr[str_len] = 0; + return (ZString)zstr; +} + +fn bool String.equals(String* str, String other_string) +{ + StringData *str1 = str.data(); + StringData *str2 = other_string.data(); + if (str1 == str2) return true; + if (!str1) return str2.len == 0; + if (!str2) return str1.len == 0; + usize str1_len = str1.len; + if (str1_len != str2.len) return false; + for (int i = 0; i < str1_len; i++) + { + if (str1.chars[i] != str2.chars[i]) return false; + } + return true; +} + +fn void String.destroy(String* str) +{ + if (!*str) return; + StringData* data = str.data(); + data.allocator.free(data); + *str = (String)null; +} + +fn bool String.less_than(String* str, String other_string) +{ + StringData* str1 = str.data(); + StringData* str2 = other_string.data(); + if (str1 == str2) return false; + if (!str1) return str2.len != 0; + if (!str2) return str1.len == 0; + usize str1_len = str1.len; + usize str2_len = str2.len; + if (str1_len != str2_len) return str1_len < str2_len; + for (int i = 0; i < str1_len; i++) + { + if (str1.chars[i] >= str2.chars[i]) return false; + } + return true; +} + +fn void String.append(String* this, char[] str) +{ + usize other_len = str.len; + if (!other_len) return; + if (!*this) + { + *this = new(str); + return; + } + this.reserve(other_len); + StringData* data = (StringData*)*this; + mem::copy(&data.chars[data.len], str.ptr, other_len); + data.len += other_len; +} + +fn Char32[] String.copy_utf32(String* this, Allocator allocator = { null, null }) +{ + return str::utf8to32(this.str(), allocator) @inline!!; +} + +fn void String.append_string(String* this, String str) +{ + StringData* other = (StringData*)str; + if (!other) return; + this.append(str.str()); +} + +fn void String.append_char(String* str, char c) +{ + if (!*str) + { + *str = new_with_capacity(MIN_CAPACITY); + } + str.reserve(1); + StringData* data = (StringData*)*str; + data.chars[data.len++] = c; +} + +private fn StringData* String.data(String* str) @inline +{ + return (StringData*)*str; +} + + +private fn void String.reserve(String* str, usize addition) +{ + StringData* data = str.data(); + if (!data) + { + *str = string::new_with_capacity(addition); + return; + } + usize len = data.len + addition; + if (data.capacity >= len) return; + usize new_capacity = data.capacity * 2; + if (new_capacity < MIN_CAPACITY) new_capacity = MIN_CAPACITY; + *str = (String)data.allocator.realloc(data, StringData.sizeof + new_capacity)!!; +} diff --git a/lib/std/core/string_iterator.c3 b/lib/std/core/string_iterator.c3 new file mode 100644 index 000000000..d3d5a1cd6 --- /dev/null +++ b/lib/std/core/string_iterator.c3 @@ -0,0 +1,25 @@ +module std::core::string::iterator; + + + +struct StringIterator +{ + char[] utf8; + usize current; +} + +fn void StringIterator.reset(StringIterator* this) +{ + this.current = 0; +} + +fn Char32! StringIterator.next(StringIterator* this) +{ + usize len = this.utf8.len; + usize current = this.current; + if (current >= len) return IteratorResult.NO_MORE_ELEMENT!; + int read = (int)(len - current < 4 ? len - current : 4); + Char32 res = str::utf8CharTo32(&this.utf8[current], &read)?; + this.current += read; + return res; +} \ No newline at end of file diff --git a/lib/std/io.c3 b/lib/std/io.c3 index 833d71e30..8e7a14111 100644 --- a/lib/std/io.c3 +++ b/lib/std/io.c3 @@ -2,9 +2,7 @@ // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::io; -import std::mem; import libc; -import std::env; struct File { diff --git a/lib/std/libc.c3 b/lib/std/libc.c3 index 82727946f..344a9aa58 100644 --- a/lib/std/libc.c3 +++ b/lib/std/libc.c3 @@ -2,11 +2,6 @@ // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module libc; -import std::cinterop; -import std::env; -import std::os::linux; -import std::os::macos; -import std::os::windows; // stdlib diff --git a/lib/std/linkedlist.c3 b/lib/std/linkedlist.c3 index 82969bfd7..8c0efecf5 100644 --- a/lib/std/linkedlist.c3 +++ b/lib/std/linkedlist.c3 @@ -2,7 +2,6 @@ // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::array::linkedlist; -import std::mem; private struct Node { diff --git a/lib/std/list.c3 b/lib/std/list.c3 index ba16e71e5..45757fecc 100644 --- a/lib/std/list.c3 +++ b/lib/std/list.c3 @@ -2,7 +2,6 @@ // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::array::list; -import std::mem; struct List { diff --git a/lib/std/str.c3 b/lib/std/str.c3 deleted file mode 100644 index 6e22999bf..000000000 --- a/lib/std/str.c3 +++ /dev/null @@ -1,59 +0,0 @@ -module std::str; -import std::mem; - -define ZString = char*; -define String = char[]; - -fn ZString copy_zstring(String s) -{ - usize len = s.len; - char* str = mem::alloc(len + 1); - mem::copy(str, s.ptr, len); - str[len] = 0; - return str; -} - -fn ZString tcopy_zstring(String s) -{ - usize len = s.len; - char* str = mem::talloc(len + 1)!!; - mem::copy(str, s.ptr, len); - str[len] = 0; - return str; -} - -fn String copy(String s) -{ - usize len = s.len; - ZString str_copy = copy_zstring(s) @inline; - return str_copy[..len]; -} - -fn String tcopy(String s) -{ - usize len = s.len; - ZString str_copy = tcopy_zstring(s) @inline; - return str_copy[..len]; -} - -fn String tconcat(String s1, String s2) -{ - usize full_len = s1.len + s2.len; - char* str = mem::talloc(full_len + 1)!!; - usize s1_len = s1.len; - mem::copy(str, s1.ptr, s1_len); - mem::copy(str + s1_len, s2.ptr, s2.len); - str[full_len] = 0; - return str[..full_len]; -} - -fn String concat(String s1, String s2) -{ - usize full_len = s1.len + s2.len; - char* str = mem::alloc(full_len + 1); - usize s1_len = s1.len; - mem::copy(str, s1.ptr, s1_len); - mem::copy(str + s1_len, s2.ptr, s2.len); - str[full_len] = 0; - return str[..full_len]; -} \ No newline at end of file diff --git a/src/build/build_options.c b/src/build/build_options.c index 4272056d5..2492f469b 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -91,6 +91,9 @@ static void usage(void) OUTPUT(" -O2 - Default optimization level."); OUTPUT(" -Os - Optimize for size."); OUTPUT(" -O3 - Aggressive optimization."); + OUTPUT(" --build-dir - Override build output directory."); + OUTPUT(" --obj-out - Override object file output directory."); + OUTPUT(" --llvm-out - Override llvm output directory for '--emit-llvm'."); OUTPUT(" --emit-llvm - Emit LLVM IR as a .ll file per module."); OUTPUT(" --target - Compile for a particular architecture + OS target."); OUTPUT(" --threads - Set the number of threads to use for compilation."); @@ -612,6 +615,24 @@ static void parse_option(BuildOptions *options) options->win.crt_linking = (WinCrtLinking)parse_multi_option(argopt, 3, wincrt_linking); return; } + if (match_longopt("build-dir")) + { + if (at_end() || next_is_opt()) error_exit("error: --build-dir needs a directory."); + options->build_dir = next_arg(); + return; + } + if (match_longopt("obj-out")) + { + if (at_end() || next_is_opt()) error_exit("error: --obj-out needs a directory."); + options->obj_out = next_arg(); + return; + } + if (match_longopt("llvm-out")) + { + if (at_end() || next_is_opt()) error_exit("error: --llvm-out needs a directory."); + options->llvm_out = next_arg(); + return; + } if (match_longopt("lib")) { if (at_end() || next_is_opt()) error_exit("error: --lib needs a name."); @@ -691,7 +712,9 @@ BuildOptions parse_arguments(int argc, const char *argv[]) .backend = BACKEND_LLVM, .x86_vector_capability = X86VECTOR_DEFAULT, .win.crt_linking = WIN_CRT_DEFAULT, - .files = NULL + .files = NULL, + .build_dir = NULL, + }; for (int i = DIAG_NONE; i < DIAG_WARNING_TYPE; i++) { diff --git a/src/build/build_options.h b/src/build/build_options.h index 9ea3303f4..b7f875b7d 100644 --- a/src/build/build_options.h +++ b/src/build/build_options.h @@ -256,6 +256,9 @@ typedef struct BuildOptions_ bool force_linker; const char *panicfn; const char *cc; + const char *build_dir; + const char *llvm_out; + const char *obj_out; RelocModel reloc_model; X86VectorCapability x86_vector_capability; bool print_keywords; @@ -309,6 +312,8 @@ typedef struct const char *cpu; const char **link_args; const char *build_dir; + const char *object_file_dir; + const char *llvm_file_dir; bool run_after_compile : 1; bool test_output : 1; bool output_headers : 1; diff --git a/src/build/builder.c b/src/build/builder.c index f0492e9cc..596921d36 100644 --- a/src/build/builder.c +++ b/src/build/builder.c @@ -61,6 +61,30 @@ ArchOsTarget default_target = ELF_RISCV64; ArchOsTarget default_target = ARCH_OS_TARGET_DEFAULT; #endif +static bool command_is_compile(CompilerCommand command) +{ + switch (command) + { + case COMMAND_COMPILE: + case COMMAND_COMPILE_ONLY: + case COMMAND_COMPILE_RUN: + return true; + case COMMAND_MISSING: + case COMMAND_GENERATE_HEADERS: + case COMMAND_INIT: + case COMMAND_BUILD: + case COMMAND_RUN: + case COMMAND_CLEAN_RUN: + case COMMAND_CLEAN: + case COMMAND_DIST: + case COMMAND_DOCS: + case COMMAND_BENCH: + case COMMAND_UNIT_TEST: + case COMMAND_PRINT_SYNTAX: + return false; + } + UNREACHABLE +} static void update_build_target_from_options(BuildTarget *target, BuildOptions *options) { switch (options->command) @@ -163,6 +187,18 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * { target->feature.x86_vector_capability = options->x86_vector_capability; } + if (command_is_compile(options->command)) + { + target->build_dir = options->build_dir ? options->build_dir : NULL; + target->object_file_dir = options->obj_out ? options->obj_out : target->build_dir; + target->llvm_file_dir = options->llvm_out ? options->llvm_out : target->build_dir; + } + else + { + target->build_dir = options->build_dir ? options->build_dir : "build"; + target->object_file_dir = options->obj_out ? options->obj_out : file_append_path(target->build_dir, "tmp"); + target->llvm_file_dir = options->llvm_out ? options->llvm_out : file_append_path(target->build_dir, "llvm_ir"); + } switch (options->compile_option) { case COMPILE_NORMAL: @@ -231,7 +267,6 @@ void init_build_target(BuildTarget *target, BuildOptions *options) Project *project = project_load(); *target = *project_select_target(project, options->target_select); - target->build_dir = "build"; update_build_target_from_options(target, options); if (target->build_dir && !file_exists(target->build_dir)) { diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 78c0c5919..cb07540fa 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -222,6 +222,27 @@ void compiler_compile(void) void **gen_contexts = VECNEW(void*, module_count); void (*task)(void *); + if (active_target.llvm_file_dir || active_target.emit_object_files) + { + if (active_target.build_dir && !file_exists(active_target.build_dir) && !dir_make(active_target.build_dir)) + { + error_exit("Failed to create build directory '%s'.", active_target.build_dir); + } + } + if (active_target.llvm_file_dir && active_target.emit_llvm) + { + if (!file_exists(active_target.llvm_file_dir) && !dir_make(active_target.llvm_file_dir)) + { + error_exit("Failed to create output directory '%s'.", active_target.llvm_file_dir); + } + } + if (active_target.object_file_dir && active_target.emit_object_files) + { + if (!file_exists(active_target.object_file_dir) && !dir_make(active_target.object_file_dir)) + { + error_exit("Failed to create output directory '%s'.", active_target.object_file_dir); + } + } switch (active_target.backend) { case BACKEND_LLVM: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 63704382d..edf1f2e49 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -583,6 +583,7 @@ typedef struct Decl_ bool is_maybe_unused : 1; bool is_must_use : 1; bool will_reflect : 1; + bool is_dynamic : 1; OperatorOverload operator : 4; union { @@ -616,8 +617,9 @@ typedef struct Decl_ Decl **methods; union { - // Unions, Fault and Struct use strukt + // Unions, Struct use strukt StructDecl strukt; + // Enums and Fault EnumDecl enums; DistinctDecl distinct_decl; BitStructDecl bitstruct; @@ -1573,7 +1575,7 @@ extern Type *type_cuint; extern const char *attribute_list[NUMBER_OF_ATTRIBUTES]; extern const char *builtin_list[NUMBER_OF_BUILTINS]; -extern const char *kw_std__builtin; +extern const char *kw_std__core; extern const char *kw_std; extern const char *kw_max; diff --git a/src/compiler/context.c b/src/compiler/context.c index 356f38576..65f22290b 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -166,7 +166,9 @@ void decl_register(Decl *decl) void unit_register_global_decl(CompilationUnit *unit, Decl *decl) { + assert(!decl->module || decl->module->is_generic); decl->module = unit->module; + switch (decl->decl_kind) { case DECL_POISONED: diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 7b8684b01..a79e7601c 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -168,6 +168,29 @@ typedef enum DOC_DIRECTIVE_ENSURE, } DocDirectiveKind; +typedef enum +{ + INTROSPECT_TYPE_VOID = 0, + INTROSPECT_TYPE_BOOL = 1, + INTROSPECT_TYPE_SIGNED_INT = 2, + INTROSPECT_TYPE_UNSIGNED_INT = 3, + INTROSPECT_TYPE_FLOAT = 4, + INTROSPECT_TYPE_TYPEID = 5, + INTROSPECT_TYPE_ANYERR = 6, + INTROSPECT_TYPE_ANY = 7, + INTROSPECT_TYPE_ENUM = 8, + INTROSPECT_TYPE_FAULT = 9, + INTROSPECT_TYPE_STRUCT = 10, + INTROSPECT_TYPE_UNION = 11, + INTROSPECT_TYPE_BITSTRUCT = 12, + INTROSPECT_TYPE_FUNC = 13, + INTROSPECT_TYPE_FAILABLE = 14, + INTROSPECT_TYPE_ARRAY = 15, + INTROSPECT_TYPE_SUBARRAY = 16, + INTROSPECT_TYPE_VECTOR = 17, + INTROSPECT_TYPE_DISTINCT = 18 +} IntrospectType; + typedef enum { EXPR_POISONED, diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 10f89dd25..0c23dad7f 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -482,7 +482,7 @@ void gencontext_emit_object_file(GenContext *context) LLVMDisposeMessage(layout); // Generate .o or .obj file - if (LLVMTargetMachineEmitToFile(context->machine, context->module, context->object_filename, LLVMObjectFile, &err)) + if (LLVMTargetMachineEmitToFile(context->machine, context->module, (char *)context->object_filename, LLVMObjectFile, &err)) { error_exit("Could not emit object file: %s", err); } @@ -712,96 +712,11 @@ void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value) } } -void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl) -{ - llvm_get_type(c, decl->type); - if (decl_is_struct_type(decl)) - { - Decl **decls = decl->strukt.members; - VECEACH(decls, i) - { - Decl *member_decl = decls[i]; - if (decl_is_struct_type(member_decl)) - { - llvm_emit_introspection_type_from_decl(c, member_decl); - } - } - } - if (decl_is_enum_kind(decl)) - { - Decl **enum_vals = decl->enums.values; - unsigned elements = vec_size(enum_vals); - LLVMTypeRef element_type = llvm_get_type(c, type_voidptr); - LLVMTypeRef elements_type = LLVMArrayType(element_type, elements); - scratch_buffer_clear(); - scratch_buffer_append(decl->extname); - scratch_buffer_append("$elements"); - LLVMValueRef enum_elements = llvm_add_global_type(c, scratch_buffer_to_string(), elements_type, 0); - LLVMSetGlobalConstant(enum_elements, 1); - llvm_set_linkage(c, decl, enum_elements); - LLVMSetInitializer(enum_elements, LLVMConstNull(elements_type)); - AlignSize alignment = type_alloca_alignment(type_voidptr); - for (unsigned i = 0; i < elements; i++) - { - AlignSize store_align; - enum_vals[i]->backend_ref = llvm_emit_array_gep_raw(c, enum_elements, elements_type, i, alignment, &store_align); - } - Decl **associated_values = decl->enums.parameters; - unsigned associated_value_count = vec_size(associated_values); - if (associated_value_count && elements) - { - LLVMValueRef *values = malloc_arena(elements * sizeof(LLVMValueRef)); - LLVMTypeRef val_type; - VECEACH(associated_values, ai) - { - val_type = NULL; - bool mixed = false; - for (unsigned i = 0; i < elements; i++) - { - BEValue value; - llvm_emit_expr(c, &value, enum_vals[i]->enum_constant.args[ai]); - assert(!llvm_value_is_addr(&value)); - LLVMValueRef llvm_value = llvm_value_is_bool(&value) ? LLVMConstZExt(value.value, c->byte_type) : value.value; - values[i] = llvm_value; - if (!val_type) - { - val_type = LLVMTypeOf(llvm_value); - continue; - } - if (val_type != LLVMTypeOf(llvm_value)) mixed = true; - } - Decl *associated_value = associated_values[ai]; - LLVMValueRef associated_value_arr = mixed ? LLVMConstStruct(values, elements, true) : LLVMConstArray(val_type, values, elements); - scratch_buffer_clear(); - scratch_buffer_append(decl->extname); - scratch_buffer_append("$$"); - scratch_buffer_append(associated_value->name); - LLVMValueRef global_ref = llvm_add_global_type(c, scratch_buffer_to_string(), LLVMTypeOf(associated_value_arr), 0); - LLVMSetInitializer(global_ref, associated_value_arr); - LLVMSetGlobalConstant(global_ref, true); - if (mixed) - { - LLVMTypeRef cast_type = llvm_get_ptr_type(c, type_get_array(associated_value->type, elements)); - associated_value->backend_ref = LLVMConstBitCast(global_ref, cast_type); - } - else - { - associated_value->backend_ref = global_ref; - } - } - } - } - scratch_buffer_clear(); - scratch_buffer_append("introspect."); - scratch_buffer_append(decl->name ? decl->name : "anon"); - LLVMValueRef global_name = llvm_add_global_var(c, scratch_buffer_to_string(), type_char, 0); - LLVMSetGlobalConstant(global_name, 1); - LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false)); - decl->type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); - llvm_set_linkage(c, decl, global_name); -} + + + void llvm_value_set_bool(BEValue *value, LLVMValueRef llvm_value) @@ -847,9 +762,6 @@ LLVMBasicBlockRef llvm_basic_block_new(GenContext *c, const char *name) return LLVMCreateBasicBlockInContext(c->context, name); } - - - static void llvm_emit_type_decls(GenContext *context, Decl *decl) { switch (decl->decl_kind) @@ -864,19 +776,17 @@ static void llvm_emit_type_decls(GenContext *context, Decl *decl) break; case DECL_TYPEDEF: break; - case DECL_DISTINCT: - // TODO - break; case DECL_ENUM_CONSTANT: case DECL_FAULTVALUE: // TODO break;; + case DECL_DISTINCT: case DECL_STRUCT: case DECL_UNION: case DECL_ENUM: case DECL_FAULT: case DECL_BITSTRUCT: - llvm_emit_introspection_type_from_decl(context, decl); + llvm_get_typeid(context, decl->type); break; case DECL_BODYPARAM: case NON_TYPE_DECLS: @@ -999,7 +909,10 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl) if (decl->define_decl.define_kind != DEFINE_TYPE_GENERIC) return llvm_get_ref(c, decl->define_decl.alias); UNREACHABLE case DECL_FAULTVALUE: - llvm_emit_introspection_type_from_decl(c, declptr(decl->enum_constant.parent)); + if (!decl->backend_ref) + { + llvm_get_typeid(c, declptr(decl->enum_constant.parent)->type); + } assert(decl->backend_ref); return decl->backend_ref; case DECL_POISONED: @@ -1036,7 +949,6 @@ void *llvm_gen(Module *module) gencontext_init(gen_context, module); gencontext_begin_module(gen_context); - VECEACH(module->units, j) { CompilationUnit *unit = module->units[j]; diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 1b240067d..50b3f6032 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -8,7 +8,7 @@ void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValue *lhs_loaded, BinaryOp binary_op); static void llvm_emit_any_pointer(GenContext *c, BEValue *any, BEValue *pointer); static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr); -static void gencontext_emit_unary_expr(GenContext *context, BEValue *value, Expr *expr); +static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr); static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *expr, int diff, bool use_mod); static inline void llvm_emit_pre_inc_dec(GenContext *c, BEValue *value, Expr *expr, int diff, bool use_mod); static inline void llvm_emit_inc_dec_change(GenContext *c, bool use_mod, BEValue *addr, BEValue *after, BEValue *before, Expr *expr, int diff); @@ -2044,6 +2044,21 @@ static inline void llvm_emit_pre_inc_dec(GenContext *c, BEValue *value, Expr *ex llvm_emit_inc_dec_change(c, use_mod, &addr, value, NULL, expr, diff); } +static inline void llvm_emit_deref(GenContext *c, BEValue *value, Expr *inner, Type *type) +{ + llvm_emit_expr(c, value, inner); + llvm_value_rvalue(c, value); + if (active_target.feature.safe_mode) + { + LLVMValueRef check = LLVMBuildICmp(c->builder, LLVMIntEQ, value->value, llvm_get_zero(c, inner->type), "checknull"); + llvm_emit_panic_on_true(c, check, "Dereference of null pointer", inner->span); + } + // Load the pointer value. + llvm_value_rvalue(c, value); + // Convert pointer to address + value->kind = BE_ADDRESS; + value->type = type; +} /** * Emit the common x++ and x-- operations. @@ -2063,7 +2078,7 @@ static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *e } -static void gencontext_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr) +static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr) { Type *type = type_reduced_from_expr(expr->unary_expr.expr); Expr *inner = expr->unary_expr.expr; @@ -2166,13 +2181,7 @@ static void gencontext_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr value->type = type_lowering(expr->type); return; case UNARYOP_DEREF: - REMINDER("insert a check for deref in debug mode"); - llvm_emit_expr(c, value, inner); - // Load the pointer value. - llvm_value_rvalue(c, value); - // Convert pointer to address - value->kind = BE_ADDRESS; - value->type = type_lowering(expr->type); + llvm_emit_deref(c, value, inner, type_lowering(expr->type)); return; case UNARYOP_INC: llvm_emit_pre_inc_dec(c, value, inner, 1, false); @@ -2313,7 +2322,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r Expr *start = exprptr(slice->slice_expr.start); Expr *end = exprptrzero(slice->slice_expr.end); - Type *parent_type = parent_expr->type->canonical; + Type *parent_type = type_flatten_distinct(parent_expr->type); BEValue parent_addr_x; llvm_emit_expr(c, &parent_addr_x, parent_expr); llvm_value_addr(c, &parent_addr_x); @@ -2325,12 +2334,13 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r switch (parent_type->type_kind) { case TYPE_POINTER: - parent_load_value = parent_base = gencontext_emit_load(c, parent_type, parent_addr); + parent_load_value = parent_base = LLVMBuildLoad2(c->builder, llvm_get_type(c, parent_type), parent_addr, ""); break; case TYPE_SUBARRAY: - parent_load_value = gencontext_emit_load(c, parent_type, parent_addr); + parent_load_value = LLVMBuildLoad2(c->builder, llvm_get_type(c, parent_type), parent_addr, ""); parent_base = LLVMBuildExtractValue(c->builder, parent_load_value, 0, ""); break; + case TYPE_FLEXIBLE_ARRAY: case TYPE_ARRAY: parent_base = parent_addr; break; @@ -2345,12 +2355,15 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r llvm_value_rvalue(c, &start_index); BEValue len = { .value = NULL }; + bool check_end = true; if (!end || slice->slice_expr.start_from_back || slice->slice_expr.end_from_back || active_target.feature.safe_mode) { switch (parent_type->type_kind) { case TYPE_POINTER: + case TYPE_FLEXIBLE_ARRAY: len.value = NULL; + check_end = false; break; case TYPE_SUBARRAY: assert(parent_load_value); @@ -2371,7 +2384,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r } // Check that index does not extend beyond the length. - if (parent_type->type_kind != TYPE_POINTER && active_target.feature.safe_mode) + if (check_end && active_target.feature.safe_mode) { assert(len.value); BEValue exceeds_size; @@ -2448,6 +2461,7 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr) switch (type->type_kind) { case TYPE_ARRAY: + case TYPE_FLEXIBLE_ARRAY: { Type *pointer_type = type_get_ptr(parent.type->array.base); // Move pointer @@ -2462,7 +2476,6 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr) case TYPE_POINTER: start_pointer = llvm_emit_pointer_inbounds_gep_raw(c, llvm_get_pointee_type(c, parent.type), parent.value, start.value); break; - case TYPE_FLEXIBLE_ARRAY: case TYPE_VECTOR: TODO default: @@ -3299,77 +3312,11 @@ static void llvm_emit_post_unary_expr(GenContext *context, BEValue *be_value, Ex false); } -void llvm_emit_derived_backend_type(GenContext *c, Type *type) -{ - llvm_get_type(c, type); - LLVMValueRef global_name = llvm_add_global_type(c, type->name, llvm_get_type(c, type_char), 0); - LLVMSetGlobalConstant(global_name, 1); - LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false)); - type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); - Decl *origin = NULL; - Type *original_type = type; - while (!origin) - { - switch (original_type->type_kind) - { - case TYPE_FAILABLE: - original_type = type->failable; - continue; - case TYPE_VECTOR: - original_type = type->array.base; - continue; - case TYPE_ARRAY: - case TYPE_SUBARRAY: - original_type = original_type->array.base; - continue; - case TYPE_POINTER: - original_type = original_type->pointer; - continue; - case TYPE_ENUM: - case TYPE_FUNC: - case TYPE_STRUCT: - case TYPE_UNION: - case TYPE_BITSTRUCT: - case TYPE_FAULTTYPE: - case TYPE_DISTINCT: - origin = type->decl; - continue; - case TYPE_TYPEDEF: - original_type = original_type->canonical; - continue; - case TYPE_INFERRED_ARRAY: - case TYPE_UNTYPED_LIST: - case TYPE_FAILABLE_ANY: - case TYPE_TYPEINFO: - UNREACHABLE - default: - goto PRIMITIVE; - } - } - llvm_set_linkage(c, origin, global_name); - return; - - PRIMITIVE: - llvm_set_weak(c, global_name); -} - void llvm_emit_typeid(GenContext *c, BEValue *be_value, Type *type) { LLVMValueRef value; type = type->canonical; - if (type_is_builtin(type->type_kind)) - { - value = llvm_const_int(c, type_usize, type->type_kind); - } - else - { - if (!type->backend_typeid) - { - llvm_emit_derived_backend_type(c, type); - } - value = type->backend_typeid; - } - llvm_value_set(be_value, value, type_typeid); + llvm_value_set(be_value, llvm_get_typeid(c, type), type_typeid); } void llvm_emit_try_assign_try_catch(GenContext *c, bool is_try, BEValue *be_value, BEValue *var_addr, BEValue *catch_addr, Expr *rhs) @@ -4818,7 +4765,8 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr) } } - llvm_add_abi_call_attributes(c, call_value, 1, non_variadic_params, params, abi_args); + assert(!prototype->ret_by_ref || prototype->ret_by_ref_abi_info->kind != ABI_ARG_INDIRECT); + llvm_add_abi_call_attributes(c, call_value, prototype->ret_by_ref ? 2 : 1, non_variadic_params, params, abi_args); if (prototype->abi_varargs) { llvm_add_abi_call_attributes(c, @@ -5346,7 +5294,7 @@ void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *expr) } else { - llvm_emit_local_decl(c, expr->try_unwrap_expr.decl); + llvm_emit_local_decl(c, expr->try_unwrap_expr.decl, &addr); llvm_value_set_decl_address(c, &addr, expr->try_unwrap_expr.decl); } assert(llvm_value_is_addr(&addr)); @@ -5362,7 +5310,7 @@ void llvm_emit_catch_unwrap(GenContext *c, BEValue *value, Expr *expr) } else if (expr->catch_unwrap_expr.decl) { - llvm_emit_local_decl(c, expr->catch_unwrap_expr.decl); + llvm_emit_local_decl(c, expr->catch_unwrap_expr.decl, &addr); llvm_value_set_decl_address(c, &addr, expr->catch_unwrap_expr.decl); } else @@ -5573,8 +5521,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_BUILTIN: UNREACHABLE; case EXPR_DECL: - llvm_emit_local_decl(c, expr->decl_expr); - llvm_value_set_decl_address(c, value, expr->decl_expr); + llvm_emit_local_decl(c, expr->decl_expr, value); return; case EXPR_SLICE_ASSIGN: llvm_emit_slice_assign(c, value, expr); @@ -5610,7 +5557,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) llvm_emit_expr_block(c, value, expr); return; case EXPR_UNARY: - gencontext_emit_unary_expr(c, value, expr); + llvm_emit_unary_expr(c, value, expr); return; case EXPR_CONST: llvm_emit_const_expr(c, value, expr); diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 04c6d2fa8..5e2cd7f13 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -79,8 +79,8 @@ typedef struct LLVMBuilderRef builder; LLVMBasicBlockRef current_block; LLVMBasicBlockRef catch_block; - char *ir_filename; - char *object_filename; + const char *ir_filename; + const char *object_filename; // The recipient of the error value in a catch(err = ...) expression. LLVMValueRef error_var; LLVMTypeRef bool_type; @@ -234,6 +234,7 @@ void llvm_value_set_decl(GenContext *c, BEValue *value, Decl *decl); void llvm_value_fold_failable(GenContext *c, BEValue *value); void llvm_value_struct_gep(GenContext *c, BEValue *element, BEValue *struct_pointer, unsigned index); +LLVMValueRef llvm_get_typeid(GenContext *context, Type *type); LLVMTypeRef llvm_abi_type(GenContext *c, AbiType type); TypeSize llvm_abi_size(GenContext *c, LLVMTypeRef type); BitSize llvm_bitsize(GenContext *c, LLVMTypeRef type); @@ -262,7 +263,6 @@ void llvm_emit_convert_value_from_coerced(GenContext *c, BEValue *result, LLVMTy void llvm_emit_coerce_store(GenContext *c, LLVMValueRef addr, AlignSize alignment, LLVMTypeRef coerced, LLVMValueRef value, LLVMTypeRef target_type); void llvm_emit_function_body(GenContext *context, Decl *decl); void llvm_emit_function_decl(GenContext *c, Decl *decl); -void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl); void llvm_set_weak(GenContext *c, LLVMValueRef global); void llvm_set_linkonce(GenContext *c, LLVMValueRef global); void llvm_set_comdat(GenContext *c, LLVMValueRef global); @@ -320,7 +320,7 @@ LLVMValueRef llvm_emit_lshr_fixed(GenContext *c, LLVMValueRef data, int shift); // -- general -- void llvm_emit_local_var_alloca(GenContext *c, Decl *decl); -LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl); +void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value); LLVMValueRef llvm_emit_aggregate_value(GenContext *c, Type *type, ...); LLVMValueRef llvm_emit_memclear_size_align(GenContext *c, LLVMValueRef ref, uint64_t size, AlignSize align, bool bitcast); void llvm_store_zero(GenContext *c, BEValue *ref); @@ -377,13 +377,6 @@ void llvm_store_decl_raw(GenContext *context, Decl *decl, LLVMValueRef value); LLVMTypeRef llvm_get_twostruct(GenContext *context, LLVMTypeRef lo, LLVMTypeRef hi); LLVMValueRef llvm_emit_coerce(GenContext *c, LLVMTypeRef coerced, BEValue *value, Type *original_type); -static inline LLVMValueRef gencontext_emit_load(GenContext *c, Type *type, LLVMValueRef value) -{ - assert(llvm_get_type(c, type) == LLVMGetElementType(LLVMTypeOf(value))); - return LLVMBuildLoad2(c->builder, llvm_get_type(c, type), value, ""); -} - - static inline LLVMValueRef decl_failable_ref(Decl *decl) { assert(decl->decl_kind == DECL_VAR); @@ -494,7 +487,6 @@ static inline LLVMValueRef llvm_const_int(GenContext *c, Type *type, uint64_t va static inline LLVMValueRef llvm_add_global_var(GenContext *c, const char *name, Type *type, AlignSize alignment) { - printf("Adding %s with %d\n", name, (int)alignment); type = type_lowering(type_no_fail(type)); LLVMValueRef ref = LLVMAddGlobal(c->module, llvm_get_type(c, type), name); LLVMSetAlignment(ref, (unsigned)alignment ? alignment : type_alloca_alignment(type)); @@ -503,7 +495,6 @@ static inline LLVMValueRef llvm_add_global_var(GenContext *c, const char *name, static inline LLVMValueRef llvm_add_global_type(GenContext *c, const char *name, LLVMTypeRef type, AlignSize alignment) { - printf("Adding %s with %d\n", name, (int)alignment); LLVMValueRef ref = LLVMAddGlobal(c->module, type, name); LLVMSetAlignment(ref, (unsigned)alignment ? alignment : LLVMPreferredAlignmentOfGlobal(c->target_data, ref)); return ref; diff --git a/src/compiler/llvm_codegen_module.c b/src/compiler/llvm_codegen_module.c index 3d382605d..0b4a24bd4 100644 --- a/src/compiler/llvm_codegen_module.c +++ b/src/compiler/llvm_codegen_module.c @@ -11,8 +11,9 @@ void gencontext_begin_module(GenContext *c) const char *result = module_create_object_file_name(c->code_module); c->ir_filename = str_printf("%s.ll", result); + if (active_target.llvm_file_dir) c->ir_filename = file_append_path(active_target.llvm_file_dir, c->ir_filename); c->object_filename = str_printf("%s%s", result, get_object_extension()); - + if (active_target.object_file_dir) c->object_filename = file_append_path(active_target.object_file_dir, c->object_filename); c->panicfn = global_context.panic_fn; c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context); c->machine = llvm_target_machine_create(); @@ -57,9 +58,32 @@ void gencontext_begin_module(GenContext *c) VECEACH(global_context.type, i) { - global_context.type[i]->backend_type = NULL; - global_context.type[i]->backend_debug_type = NULL; - global_context.type[i]->backend_typeid = NULL; + Type *type = global_context.type[i]; + type->backend_type = NULL; + type->backend_debug_type = NULL; + type->backend_typeid = NULL; + switch (type->type_kind) + { + case TYPE_ENUM: + case TYPE_FAULTTYPE: + { + Decl **values = type->decl->enums.values; + VECEACH(values, j) + { + values[j]->backend_ref = NULL; + } + FALLTHROUGH; + } + case TYPE_STRUCT: + case TYPE_UNION: + case TYPE_DISTINCT: + type->decl->backend_ref = NULL; + break; + case TYPE_FUNC: + // TODO + default: + break; + } } if (c->panicfn) c->panicfn->backend_ref = NULL; diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index b5a6b0974..2742c632c 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -24,7 +24,7 @@ void llvm_emit_compound_stmt(GenContext *c, Ast *ast) /** * This emits a local declaration. */ -LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl) +void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value) { // 1. Get the declaration and the LLVM type. Type *var_type = type_lowering(type_no_fail(decl->type)); @@ -35,7 +35,11 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl) if (decl->var.is_static) { // In defers we might already have generated this variable. - if (decl->backend_ref) return decl->backend_ref; + if (decl->backend_ref) + { + llvm_value_set_decl(c, value, decl); + return; + } void *builder = c->builder; c->builder = NULL; decl->backend_ref = llvm_add_global_var(c, "tempglobal", var_type, decl->alignment); @@ -48,12 +52,14 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl) } llvm_emit_global_variable_init(c, decl); c->builder = builder; - return decl->backend_ref; + llvm_value_set_decl(c, value, decl); + return; } assert(!decl->backend_ref); llvm_emit_local_var_alloca(c, decl); Expr *init = decl->var.init_expr; - if (IS_FAILABLE(decl)) + bool is_failable = IS_FAILABLE(decl); + if (is_failable) { scratch_buffer_clear(); scratch_buffer_append(decl->name); @@ -64,15 +70,18 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl) if (init) { - // If we don't have undef, then make an assign. - if (!decl->var.no_init) + llvm_value_set_decl_address(c, value, decl); + value->kind = BE_ADDRESS; + BEValue res = llvm_emit_assign_expr(c, value, decl->var.init_expr, decl->var.failable_ref); + if (!is_failable) *value = res; + } + else if (decl->var.no_init) + { + llvm_value_set(value, LLVMGetUndef(alloc_type), decl->type); + if (decl->var.failable_ref) { - BEValue value; - llvm_value_set_decl_address(c, &value, decl); - value.kind = BE_ADDRESS; - llvm_emit_assign_expr(c, &value, decl->var.init_expr, decl->var.failable_ref); + LLVMBuildStore(c->builder, LLVMGetUndef(llvm_get_type(c, type_anyerr)), decl->var.failable_ref); } - // TODO trap on undef in debug mode. } else { @@ -86,16 +95,16 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl) if (type_is_builtin(type->type_kind) || type->type_kind == TYPE_POINTER) { llvm_emit_store(c, decl, LLVMConstNull(alloc_type)); + llvm_value_set(value, LLVMConstNull(alloc_type), type); } else { - BEValue value; - llvm_value_set_decl_address(c, &value, decl); - value.kind = BE_ADDRESS; - llvm_store_zero(c, &value); + llvm_value_set_decl_address(c, value, decl); + value->kind = BE_ADDRESS; + llvm_store_zero(c, value); + llvm_value_set(value, llvm_get_zero(c, type), type); } } - return decl->backend_ref; } void llvm_emit_decl_expr_list_ignore_result(GenContext *context, Expr *expr) @@ -124,7 +133,8 @@ void llvm_emit_decl_expr_list(GenContext *context, BEValue *be_value, Expr *expr if (last->expr_kind == EXPR_DECL) { type = last->decl_expr->var.type_info->type; - LLVMValueRef decl_value = llvm_emit_local_decl(context, last->decl_expr); + + LLVMValueRef decl_value = llvm_get_ref(context, last->decl_expr); if (bool_cast && last->decl_expr->var.unwrap) { llvm_value_set_bool(be_value, LLVMConstInt(context->bool_type, 1, false)); @@ -1134,8 +1144,11 @@ void llvm_emit_stmt(GenContext *c, Ast *ast) gencontext_emit_expr_stmt(c, ast); break; case AST_DECLARE_STMT: - llvm_emit_local_decl(c, ast->declare_stmt); + { + BEValue value; + llvm_emit_local_decl(c, ast->declare_stmt, &value); break; + } case AST_BREAK_STMT: llvm_emit_break(c, ast); break; diff --git a/src/compiler/llvm_codegen_type.c b/src/compiler/llvm_codegen_type.c index 11e775841..550dc42a9 100644 --- a/src/compiler/llvm_codegen_type.c +++ b/src/compiler/llvm_codegen_type.c @@ -447,3 +447,327 @@ LLVMTypeRef llvm_abi_type(GenContext *c, AbiType type) if (abi_type_is_type(type)) return llvm_get_type(c, type.type); return LLVMIntTypeInContext(c->context, type.int_bits_plus_1 - 1); } + +static inline Module *type_base_module(Type *type) +{ + RETRY: + switch (type->type_kind) + { + case TYPE_POISONED: + case TYPE_VOID: + case ALL_INTS: + case ALL_FLOATS: + case TYPE_BOOL: + case TYPE_ANY: + case TYPE_ANYERR: + case TYPE_TYPEID: + return NULL; + case TYPE_POINTER: + type = type->pointer; + goto RETRY; + case TYPE_ENUM: + case TYPE_FUNC: + case TYPE_STRUCT: + case TYPE_UNION: + case TYPE_BITSTRUCT: + case TYPE_FAULTTYPE: + case TYPE_DISTINCT: + return type->decl->module; + case TYPE_TYPEDEF: + type = type->canonical; + goto RETRY; + case TYPE_ARRAY: + case TYPE_SUBARRAY: + case TYPE_INFERRED_ARRAY: + case TYPE_FLEXIBLE_ARRAY: + case TYPE_VECTOR: + type = type->array.base; + goto RETRY; + case TYPE_FAILABLE: + type = type->failable; + goto RETRY; + case TYPE_UNTYPED_LIST: + case TYPE_FAILABLE_ANY: + case TYPE_TYPEINFO: + UNREACHABLE + } + UNREACHABLE +} +LLVMValueRef llvm_get_introspection_for_derived_type(GenContext *c, IntrospectType kind, Type *type, Type *inner, LLVMValueRef extra) +{ + LLVMValueRef value = llvm_get_typeid(c, inner); + LLVMValueRef values[3] = { llvm_const_int(c, type_char, kind), value }; + int count = 2; + if (extra) + { + values[2] = extra; + count = 3; + } + LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, count, false); + scratch_buffer_clear(); + scratch_buffer_append(".typeid."); + Module *module = type_base_module(inner); + if (module) + { + scratch_buffer_append(module->name->module); + scratch_buffer_append_char('.'); + } + scratch_buffer_append(type->name); + LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(strukt), scratch_buffer_to_string()); + LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(strukt))); + LLVMSetGlobalConstant(global_name, 1); + LLVMSetInitializer(global_name, strukt); + llvm_set_linkonce(c, global_name); + return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); +} + +static LLVMValueRef llvm_get_introspection_for_builtin_type(GenContext *c, Type *type, IntrospectType introspect_type, int bits) +{ + LLVMValueRef values[2]; + int count = 1; + values[0] = llvm_const_int(c, type_char, introspect_type); + if (bits) + { + values[1] = llvm_const_int(c, type_ushort, bits); + count = 2; + } + LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, count, false); + scratch_buffer_clear(); + scratch_buffer_append(".typeid."); + scratch_buffer_append(type->name); + LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(strukt), scratch_buffer_to_string()); + LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(strukt))); + LLVMSetGlobalConstant(global_name, 1); + LLVMSetInitializer(global_name, strukt); + llvm_set_linkonce(c, global_name); + return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); +} + +static LLVMValueRef llvm_get_introspection_weak(GenContext *c, Type *type, const char *name, LLVMValueRef data) +{ + scratch_buffer_clear(); + scratch_buffer_append(".typeid."); + scratch_buffer_append(name); + LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(data), scratch_buffer_to_string()); + LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(data))); + LLVMSetGlobalConstant(global_name, 1); + LLVMSetInitializer(global_name, data); + llvm_set_linkonce(c, global_name); + return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); +} + +static LLVMValueRef llvm_get_introspection_external(GenContext *c, Type *type, LLVMValueRef data) +{ + scratch_buffer_clear(); + scratch_buffer_append(".typeid."); + scratch_buffer_append(type->name); + LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(data), scratch_buffer_to_string()); + LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(data))); + LLVMSetLinkage(global_name, LLVMExternalLinkage); + return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); +} + +static LLVMValueRef llvm_get_introspection_for_enum(GenContext *c, Type *type) +{ + Decl *decl = type->decl; + bool is_external = decl->module != c->code_module; + bool is_dynamic = decl->is_dynamic; + + Decl **enum_vals = decl->enums.values; + unsigned elements = vec_size(enum_vals); + Decl **associated_values = decl->enums.parameters; + unsigned associated_value_count = vec_size(associated_values); + if (is_external && is_dynamic) + { + elements = 0; + } + LLVMValueRef en_values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_ENUM ), + llvm_const_int(c, type_usize, elements), + llvm_const_int(c, type_usize, associated_value_count) }; + LLVMValueRef strukt = LLVMConstStructInContext(c->context, en_values, 3, false); + + if (is_external && !is_dynamic) + { + return llvm_get_introspection_external(c, type, strukt); + } + + LLVMValueRef val = llvm_get_introspection_weak(c, type, decl_get_extname(decl), strukt); + if (!associated_value_count) return val; + + LLVMValueRef *values = elements ? malloc_arena(elements * sizeof(LLVMValueRef)) : NULL; + LLVMTypeRef val_type; + VECEACH(associated_values, ai) + { + val_type = NULL; + bool mixed = false; + for (unsigned i = 0; i < elements; i++) + { + BEValue value; + llvm_emit_expr(c, &value, enum_vals[i]->enum_constant.args[ai]); + assert(!llvm_value_is_addr(&value)); + LLVMValueRef llvm_value = llvm_value_is_bool(&value) ? LLVMConstZExt(value.value, c->byte_type) + : value.value; + values[i] = llvm_value; + if (!val_type) + { + val_type = LLVMTypeOf(llvm_value); + continue; + } + if (val_type != LLVMTypeOf(llvm_value)) mixed = true; + } + Decl *associated_value = associated_values[ai]; + LLVMValueRef associated_value_arr = mixed ? LLVMConstStruct(values, elements, true) : LLVMConstArray(val_type, + values, + elements); + scratch_buffer_clear(); + scratch_buffer_append(decl->extname); + scratch_buffer_append("."); + scratch_buffer_append(associated_value->name); + LLVMValueRef global_ref = llvm_add_global_type(c, + scratch_buffer_to_string(), + LLVMTypeOf(associated_value_arr), + 0); + llvm_set_linkonce(c, global_ref); + LLVMSetInitializer(global_ref, associated_value_arr); + LLVMSetGlobalConstant(global_ref, true); + if (mixed) + { + LLVMTypeRef cast_type = llvm_get_ptr_type(c, type_get_array(associated_value->type, elements)); + associated_value->backend_ref = LLVMConstBitCast(global_ref, cast_type); + } + else + { + associated_value->backend_ref = global_ref; + } + } + return val; +} + +static LLVMValueRef llvm_get_introspection_for_struct_union(GenContext *c, Type *type) +{ + Decl *decl = type->decl; + Decl **decls = decl->strukt.members; + VECEACH(decls, i) + { + Decl *member_decl = decls[i]; + if (decl_is_struct_type(member_decl)) + { + llvm_get_typeid(c, member_decl->type); + } + } + LLVMValueRef values[] = { llvm_const_int(c, type_char, decl->decl_kind == DECL_STRUCT ? INTROSPECT_TYPE_STRUCT : INTROSPECT_TYPE_UNION ), + llvm_const_int(c, type_usize, vec_size(decls)) }; + LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 2, false); + return llvm_get_introspection_weak(c, type, decl_get_extname(decl), strukt); +} + +static LLVMValueRef llvm_get_introspection_for_fault(GenContext *c, Type *type) +{ + Decl *decl = type->decl; + Decl **fault_vals = decl->enums.values; + unsigned elements = vec_size(fault_vals); + AlignSize store_align; + for (unsigned i = 0; i < elements; i++) + { + scratch_buffer_clear(); + scratch_buffer_append(decl_get_extname(decl)); + scratch_buffer_append_char('.'); + Decl *val = fault_vals[i]; + scratch_buffer_append(val->name); + LLVMValueRef global_name = llvm_add_global_var(c, scratch_buffer_to_string(), type_char, 0); + LLVMSetGlobalConstant(global_name, 1); + LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false)); + llvm_set_linkonce(c, global_name); + val->backend_ref = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); + } + LLVMTypeRef element_type = llvm_get_type(c, type_typeid); + LLVMTypeRef elements_type = LLVMArrayType(element_type, elements); + LLVMValueRef start = LLVMConstNull(elements_type); + for (unsigned i = 0; i < elements; i++) + { + start = LLVMConstInsertValue(start, LLVMConstBitCast(fault_vals[i]->backend_ref, element_type), &i, 1); + } + LLVMValueRef values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_FAULT ), llvm_const_int(c, type_usize, elements), start }; + LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 3, false); + return llvm_get_introspection_weak(c, type, decl_get_extname(decl), strukt); +} + + +LLVMValueRef llvm_get_typeid(GenContext *c, Type *type) +{ + if (type->backend_typeid) return type->backend_typeid; + + switch (type->type_kind) + { + case TYPE_FAILABLE: + return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_FAILABLE, type, type->failable, NULL); + case TYPE_FLEXIBLE_ARRAY: + return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->array.base, + llvm_const_int(c, type_usize, 0)); + case TYPE_VECTOR: + return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_VECTOR, type, type->array.base, + llvm_const_int(c, type_usize, type->array.len)); + case TYPE_ARRAY: + return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->array.base, + llvm_const_int(c, type_usize, type->array.len)); + case TYPE_SUBARRAY: + return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->array.base, NULL); + case TYPE_POINTER: + return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->pointer, NULL); + case TYPE_DISTINCT: + return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_DISTINCT, type, type->decl->distinct_decl.base_type, NULL); + case TYPE_ENUM: + return llvm_get_introspection_for_enum(c, type); + case TYPE_FAULTTYPE: + return llvm_get_introspection_for_fault(c, type); + case TYPE_STRUCT: + case TYPE_UNION: + return llvm_get_introspection_for_struct_union(c, type); + case TYPE_FUNC: + { + LLVMValueRef values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_FUNC ) }; + LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 1, false); + return llvm_get_introspection_weak(c, type, decl_get_extname(type->decl), strukt); + + } + case TYPE_BITSTRUCT: + { + LLVMValueRef values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_BITSTRUCT ) }; + LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 1, false); + return llvm_get_introspection_weak(c, type, decl_get_extname(type->decl), strukt); + } + case TYPE_TYPEDEF: + return llvm_get_typeid(c, type->canonical); + case TYPE_INFERRED_ARRAY: + case TYPE_UNTYPED_LIST: + case TYPE_FAILABLE_ANY: + case TYPE_TYPEINFO: + UNREACHABLE + case TYPE_VOID: + return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_VOID, 0); + case TYPE_BOOL: + return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_BOOL, 0); + case ALL_SIGNED_INTS: + return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_SIGNED_INT, + type_kind_bitsize(type->type_kind)); + case ALL_UNSIGNED_INTS: + return llvm_get_introspection_for_builtin_type(c, + type, + INTROSPECT_TYPE_UNSIGNED_INT, + type_kind_bitsize(type->type_kind)); + case ALL_FLOATS: + return llvm_get_introspection_for_builtin_type(c, + type, + INTROSPECT_TYPE_FLOAT, + type_kind_bitsize(type->type_kind)); + case TYPE_ANYERR: + return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_ANYERR, 0); + case TYPE_ANY: + return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_ANY, 0); + case TYPE_TYPEID: + return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_TYPEID, 0); + case TYPE_POISONED: + UNREACHABLE + } + UNREACHABLE +} \ No newline at end of file diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index fe66bce5f..168c61f50 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -617,7 +617,7 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool if (to == type_voidptr || from == type_voidptr) return true; // Special handling of int* = int[4]* - if (from->pointer->type_kind == TYPE_ARRAY) + if (from->pointer->type_kind == TYPE_ARRAY || from->pointer->type_kind == TYPE_FLEXIBLE_ARRAY) { if (type_is_subtype(to->pointer, from->pointer->array.base)) { diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 4b16a314c..13e012c2a 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -68,8 +68,10 @@ static inline bool sema_check_no_duplicate_parameter(Decl **decls, Decl *current -static inline bool sema_analyse_struct_member(SemaContext *context, Decl *decl) +static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent, Decl *decl) { + assert(!decl->module || decl->module->is_generic); + decl->module = parent->module; if (decl->name) { Decl *other = sema_resolve_symbol_in_current_dynamic_scope(context, decl->name); @@ -125,7 +127,7 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl ** decl_poison(decl); continue; } - if (!sema_analyse_struct_member(context, member)) + if (!sema_analyse_struct_member(context, decl, member)) { if (decl_ok(decl)) { @@ -224,7 +226,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl * decl_poison(decl); continue; } - if (!sema_analyse_struct_member(context, member)) + if (!sema_analyse_struct_member(context, decl, member)) { if (decl_ok(decl)) { @@ -1614,6 +1616,7 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl) } Decl *function = decl_new(DECL_FUNC, NULL, decl->span, VISIBLE_EXTERN); function->name = kw_mainstub; + function->module = decl->module; function->extname = kw_main; function->has_extname = true; function->func_decl.function_signature.returntype = type_infoid(type_info_new_base(type_cint, decl->span)); @@ -2286,7 +2289,7 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl) } decl->resolve_status = RESOLVE_RUNNING; - decl->module = context->unit->module; + assert(decl->module); switch (decl->decl_kind) { case DECL_BITSTRUCT: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 355144089..f34c3eda6 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -882,6 +882,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Decl *ambiguous_decl = NULL; Decl *private_symbol = NULL; + assert(expr && expr->identifier_expr.ident); DEBUG_LOG("Now resolving %s", expr->identifier_expr.ident); DeclId body_param; @@ -992,6 +993,8 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr) { + assert(expr && expr->ct_ident_expr.identifier); + DEBUG_LOG("Now resolving %s", expr->ct_ident_expr.identifier); Decl *decl = sema_resolve_symbol(context, expr->ct_ident_expr.identifier, NULL, expr->span); @@ -1012,6 +1015,7 @@ static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *e static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Expr *expr) { + assert(expr && expr->hash_ident_expr.identifier); DEBUG_LOG("Now resolving %s", expr->hash_ident_expr.identifier); Decl *decl = sema_resolve_symbol(context, expr->hash_ident_expr.identifier, NULL, expr->span); @@ -4292,6 +4296,7 @@ static inline bool sema_expr_analyse_ct_identifier_lvalue(SemaContext *context, Decl *ambiguous_decl = NULL; Decl *private_symbol = NULL; + assert(expr && expr->ct_ident_expr.identifier); DEBUG_LOG("Now resolving %s", expr->ct_ident_expr.identifier); Decl *decl = sema_find_symbol(context, expr->ct_ident_expr.identifier); @@ -7277,11 +7282,6 @@ bool splitpathref(const char *string, ArraySize len, Path **path_ref, const char if (!*ident_ref) { scratch_buffer_clear(); - if (*path_ref) - { - scratch_buffer_append_len((*path_ref)->module, (*path_ref)->len); - scratch_buffer_append("::"); - } scratch_buffer_append_len(string, len); *ident_ref = scratch_buffer_to_string(); *type_ref = TOKEN_INVALID_TOKEN; diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index cbca16d8a..fb4922a6c 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -165,11 +165,11 @@ static bool decl_is_visible(CompilationUnit *unit, Decl *decl) // 2. Same top module as unit -> ok if (top == unit->module->top_module) return true; - // 3. We want to check std::builtin + // 3. We want to check std::core Module *lookup = module; while (lookup) { - if (lookup->name->module == kw_std__builtin) return true; + if (lookup->name->module == kw_std__core) return true; lookup = lookup->parent_module; } diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index e09a1ec49..e83f4970a 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -304,7 +304,7 @@ void sema_analysis_run(void) if (active_target.panicfn || !active_target.no_stdlib) { - const char *panicfn = active_target.panicfn ? active_target.panicfn : "std::builtin::panic"; + const char *panicfn = active_target.panicfn ? active_target.panicfn : "std::core::builtin::panic"; Path *path; const char *ident; TokenType type; diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 2dd6c039e..4919b5734 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -39,7 +39,7 @@ static SymTab symtab; const char *attribute_list[NUMBER_OF_ATTRIBUTES]; const char *builtin_list[NUMBER_OF_BUILTINS]; -const char *kw_std__builtin; +const char *kw_std__core; const char *kw_in; const char *kw_out; const char *kw_inout; @@ -128,7 +128,7 @@ void symtab_init(uint32_t capacity) kw_FUNC = KW_DEF("FUNC"); type = TOKEN_IDENT; - kw_std__builtin = KW_DEF("std::builtin"); + kw_std__core = KW_DEF("std::core"); kw_sizeof = KW_DEF("sizeof"); kw_in = KW_DEF("in"); kw_out = KW_DEF("out"); @@ -152,7 +152,6 @@ void symtab_init(uint32_t capacity) kw_ordinal = KW_DEF("ordinal"); kw_ptr = KW_DEF("ptr"); kw_pure = KW_DEF("pure"); - KW_DEF("require"); kw_std = KW_DEF("std"); kw_values = KW_DEF("values"); kw_incr = KW_DEF("incr"); diff --git a/src/compiler/types.c b/src/compiler/types.c index 3574c3e35..230b8a1f1 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -1049,7 +1049,6 @@ static inline Type *func_create_new_func_proto(FunctionSignature *sig, CallABI a } c_abi_func_create(proto); - Type *type = type_new(TYPE_FUNC, "#Function"); type->func.prototype = proto; type->canonical = type; diff --git a/src/main.c b/src/main.c index 13fbe6187..9f0f9b4b4 100644 --- a/src/main.c +++ b/src/main.c @@ -27,6 +27,8 @@ int main_real(int argc, const char *argv[]) { bench_begin(); + // Setjmp will allow us to add things like fuzzing with + // easy restarts. int result = setjmp(on_error_jump); if (result) { diff --git a/src/version.h b/src/version.h index 9bd12da27..3ac708591 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.6" \ No newline at end of file +#define COMPILER_VERSION "0.2.7" \ No newline at end of file diff --git a/test/src/tester.py b/test/src/tester.py index 0362746eb..124810bdb 100644 --- a/test/src/tester.py +++ b/test/src/tester.py @@ -229,8 +229,14 @@ class Issues: lines = reader.read().splitlines() searched_line = 0 current_line = 0 - while searched_line < len(file.expected_lines): + total_lines = len(file.expected_lines) + while searched_line < total_lines: line = file.expected_lines[searched_line].strip() + next_line = None + if searched_line + 1 < total_lines: + alt_line = file.expected_lines[searched_line + 1].strip() + if alt_line.startswith("??"): + next_line = alt_line[2:].strip() if line == "": searched_line += 1 continue @@ -243,8 +249,11 @@ class Issues: current_line += 1 searched_line += 1 continue + if next_line != None and next_line in lines[current_line]: + current_line += 1 + searched_line += 2 + continue current_line += 1 - if not self.has_errors: self.conf.numsuccess += 1 print(" Passed.") diff --git a/test/test_suite/abi/regcall_expand.c3t b/test/test_suite/abi/regcall_expand.c3t index 1db924250..bc6f01fb3 100644 --- a/test/test_suite/abi/regcall_expand.c3t +++ b/test/test_suite/abi/regcall_expand.c3t @@ -21,9 +21,9 @@ fn int main() %Foo = type { [2 x float] } -$introspect.Foo = comdat any +$.typeid.test.Foo = comdat any -@introspect.Foo = linkonce constant i8 1 +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, comdat, align 8 declare void @printf(i8*, ...) #0 diff --git a/test/test_suite/assert/unreachable.c3t b/test/test_suite/assert/unreachable.c3t index 7aaf8ab46..6e6b652b9 100644 --- a/test/test_suite/assert/unreachable.c3t +++ b/test/test_suite/assert/unreachable.c3t @@ -28,7 +28,7 @@ if.then: ; preds = %entry ret void if.exit: ; preds = %entry - call void @"std::builtin.panic"(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i32 0, i32 0), i32 10) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i32 0, i32 0), i32 10) unreachable after.unreachable: ; No predecessors! diff --git a/test/test_suite/attributes/user_defined_attributes.c3t b/test/test_suite/attributes/user_defined_attributes.c3t index e2d94b9c8..f7643cfe8 100644 --- a/test/test_suite/attributes/user_defined_attributes.c3t +++ b/test/test_suite/attributes/user_defined_attributes.c3t @@ -28,7 +28,7 @@ fn void main() @TestZero %Foo = type { i32, [1020 x i8], i32, [1020 x i8] } -@introspect.Foo = linkonce constant i8 1 +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 @test.f = local_unnamed_addr global %Foo zeroinitializer, align 1024 define void @test.testme() #0 { diff --git a/test/test_suite/enumerations/enum_associated_value.c3t b/test/test_suite/enumerations/enum_associated_value.c3t index 7161f0592..8487dddec 100644 --- a/test/test_suite/enumerations/enum_associated_value.c3t +++ b/test/test_suite/enumerations/enum_associated_value.c3t @@ -18,12 +18,11 @@ fn void main() /* #expect: test.ll -@"test.Foo$elements" = linkonce constant [2 x i8*] zeroinitializer -@"test.Foo$$val" = constant [2 x i32] [i32 123, i32 333] +@.typeid.test.Foo = linkonce constant { i8, i64, i64 } { i8 8, i64 2, i64 2 }, align 8 +@test.Foo.val = linkonce constant [2 x i32] [i32 123, i32 333], align 4 @.str = private unnamed_addr constant [9 x i8] c"Number A\00", align 1 @.str.1 = private unnamed_addr constant [9 x i8] c"Number B\00", align 1 -@"test.Foo$$testme" = constant [2 x i8*] [i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i32 0, i32 0)] -@introspect.Foo = linkonce constant i8 1 +@test.Foo.testme = linkonce constant [2 x i8*] [i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i32 0, i32 0)], align 8 @.str.2 = private unnamed_addr constant [17 x i8] c"%d (%s) %d (%s)\0A\00", align 1 ; Function Attrs: nounwind @@ -36,16 +35,16 @@ entry: store i32 1, i32* %f, align 4 store i32 0, i32* %g, align 4 %0 = load i32, i32* %f, align 4 - %1 = getelementptr inbounds [2 x i32], [2 x i32]* @"test.Foo$$val", i32 0, i32 %0 + %1 = getelementptr inbounds [2 x i32], [2 x i32]* @test.Foo.val, i32 0, i32 %0 %2 = load i32, i32* %1, align 4 %3 = load i32, i32* %f, align 4 - %4 = getelementptr inbounds [2 x i8*], [2 x i8*]* @"test.Foo$$testme", i32 0, i32 %3 + %4 = getelementptr inbounds [2 x i8*], [2 x i8*]* @test.Foo.testme, i32 0, i32 %3 %5 = load i8*, i8** %4, align 8 %6 = load i32, i32* %g, align 4 - %7 = getelementptr inbounds [2 x i32], [2 x i32]* @"test.Foo$$val", i32 0, i32 %6 + %7 = getelementptr inbounds [2 x i32], [2 x i32]* @test.Foo.val, i32 0, i32 %6 %8 = load i32, i32* %7, align 4 %9 = load i32, i32* %g, align 4 - %10 = getelementptr inbounds [2 x i8*], [2 x i8*]* @"test.Foo$$testme", i32 0, i32 %9 + %10 = getelementptr inbounds [2 x i8*], [2 x i8*]* @test.Foo.testme, i32 0, i32 %9 %11 = load i8*, i8** %10, align 8 %12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.2, i32 0, i32 0), i32 %2, i8* %5, i32 %8, i8* %11) ret void diff --git a/test/test_suite/errors/anyerr_void.c3t b/test/test_suite/errors/anyerr_void.c3t index c50dd9656..67013d1fb 100644 --- a/test/test_suite/errors/anyerr_void.c3t +++ b/test/test_suite/errors/anyerr_void.c3t @@ -29,7 +29,7 @@ fn void main() ; Function Attrs: nounwind define i64 @anyerr_void.errorThing() #0 { entry: - ret i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"anyerr_void.MyError$elements", i64 0, i64 1) to i64) + ret i64 ptrtoint (i8* @anyerr_void.MyError.BAR to i64) } ; Function Attrs: nounwind @@ -65,8 +65,8 @@ noerr_block: ; preds = %after.errcheck, %er store i64 %1, i64* %z, align 8 %2 = load i64, i64* %z, align 8 call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i64 %2) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"anyerr_void.MyError$elements", i64 0, i64 1) to i64)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i64 ptrtoint ([2 x i8*]* @"anyerr_void.MyError$elements" to i64)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), i64 ptrtoint (i8* @anyerr_void.MyError.BAR to i64)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i64 ptrtoint (i8* @anyerr_void.MyError.FOO to i64)) store i64 0, i64* %error_var1, align 8 %3 = call i64 @anyerr_void.errorThing2() %not_err2 = icmp eq i64 %3, 0 diff --git a/test/test_suite/errors/error_else.c3t b/test/test_suite/errors/error_else.c3t new file mode 100644 index 000000000..cf6ce3134 --- /dev/null +++ b/test/test_suite/errors/error_else.c3t @@ -0,0 +1,22 @@ +module foo; + +fault Baz +{ + TEST +} + +module bar; +import foo; + +fn int! abc() +{ + return Baz.TEST!; +} + +module baz; +import foo; + +fn int! abc() +{ + return Baz.TEST!; +} diff --git a/test/test_suite/errors/error_regression_2.c3t b/test/test_suite/errors/error_regression_2.c3t index 4632edd1d..519ff784b 100644 --- a/test/test_suite/errors/error_regression_2.c3t +++ b/test/test_suite/errors/error_regression_2.c3t @@ -318,7 +318,7 @@ entry: br i1 %12, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint ([2 x i8*]* @"test.ReadError$elements" to i64) + ret i64 ptrtoint (i8* @test.ReadError.BAD_READ to i64) if.exit: ; preds = %entry %13 = bitcast %"char[]"* %url to { i8*, i64 }* @@ -366,7 +366,7 @@ if.then15: ; preds = %if.exit9 store %"char[]"* null, %"char[]"** %33, align 8 %34 = load %Head, %Head* %literal18, align 8 store %Head %34, %Head* %value, align 8 - %35 = call i8* @"std::mem.alloc"(i64 8, i64 0) + %35 = call i8* @"std::core::mem.alloc"(i64 8, i64 0) %ptrptr = bitcast i8* %35 to %Head* store %Head* %ptrptr, %Head** %temp, align 8 %36 = load %Head*, %Head** %temp, align 8 @@ -374,7 +374,7 @@ if.then15: ; preds = %if.exit9 br i1 %not, label %if.then19, label %if.exit20 if.then19: ; preds = %if.then15 - store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var, align 8 + store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var, align 8 br label %guard_block if.exit20: ; preds = %if.then15 @@ -418,7 +418,7 @@ if.then27: ; preds = %if.exit21 store %"char[]"* null, %"char[]"** %53, align 8 %54 = getelementptr inbounds %Head, %Head* %literal32, i32 0, i32 0 store %"char[]" { i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i32 0, i32 0), i64 0 }, %"char[]"* %value34, align 8 - %55 = call i8* @"std::mem.alloc"(i64 16, i64 0) + %55 = call i8* @"std::core::mem.alloc"(i64 16, i64 0) %ptrptr36 = bitcast i8* %55 to %"char[]"* store %"char[]"* %ptrptr36, %"char[]"** %temp35, align 8 %56 = load %"char[]"*, %"char[]"** %temp35, align 8 @@ -426,7 +426,7 @@ if.then27: ; preds = %if.exit21 br i1 %not37, label %if.then38, label %if.exit39 if.then38: ; preds = %if.then27 - store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var33, align 8 + store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var33, align 8 br label %guard_block40 if.exit39: ; preds = %if.then27 @@ -445,7 +445,7 @@ noerr_block41: ; preds = %if.exit39 store %"char[]"* %61, %"char[]"** %54, align 8 %62 = load %Head, %Head* %literal32, align 8 store %Head %62, %Head* %value31, align 8 - %63 = call i8* @"std::mem.alloc"(i64 8, i64 0) + %63 = call i8* @"std::core::mem.alloc"(i64 8, i64 0) %ptrptr43 = bitcast i8* %63 to %Head* store %Head* %ptrptr43, %Head** %temp42, align 8 %64 = load %Head*, %Head** %temp42, align 8 @@ -453,7 +453,7 @@ noerr_block41: ; preds = %if.exit39 br i1 %not44, label %if.then45, label %if.exit46 if.then45: ; preds = %noerr_block41 - store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var30, align 8 + store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var30, align 8 br label %guard_block47 if.exit46: ; preds = %noerr_block41 @@ -486,14 +486,14 @@ if.exit49: ; preds = %if.exit21 %77 = load i32, i32* %len, align 4 %siuiext = sext i32 %77 to i64 %add = add i64 %siuiext, 1 - %78 = call i8* @"std::mem.alloc"(i64 %add, i64 0) + %78 = call i8* @"std::core::mem.alloc"(i64 %add, i64 0) store i8* %78, i8** %str, align 8 %79 = load i8*, i8** %str, align 8 %not50 = icmp eq i8* %79, null br i1 %not50, label %if.then51, label %if.exit52 if.then51: ; preds = %if.exit49 - ret i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64) + ret i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64) if.exit52: ; preds = %if.exit49 %80 = load i8*, i8** %str, align 8 @@ -520,7 +520,7 @@ if.exit52: ; preds = %if.exit49 %93 = insertvalue %"char[]" undef, i8* %ptroffset, 0 %94 = insertvalue %"char[]" %93, i64 %size, 1 store %"char[]" %94, %"char[]"* %value62, align 8 - %95 = call i8* @"std::mem.alloc"(i64 16, i64 0) + %95 = call i8* @"std::core::mem.alloc"(i64 16, i64 0) %ptrptr64 = bitcast i8* %95 to %"char[]"* store %"char[]"* %ptrptr64, %"char[]"** %temp63, align 8 %96 = load %"char[]"*, %"char[]"** %temp63, align 8 @@ -528,7 +528,7 @@ if.exit52: ; preds = %if.exit49 br i1 %not65, label %if.then66, label %if.exit67 if.then66: ; preds = %if.exit52 - store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var61, align 8 + store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var61, align 8 br label %guard_block68 if.exit67: ; preds = %if.exit52 @@ -547,7 +547,7 @@ noerr_block69: ; preds = %if.exit67 store %"char[]"* %101, %"char[]"** %89, align 8 %102 = load %Head, %Head* %literal60, align 8 store %Head %102, %Head* %value59, align 8 - %103 = call i8* @"std::mem.alloc"(i64 8, i64 0) + %103 = call i8* @"std::core::mem.alloc"(i64 8, i64 0) %ptrptr71 = bitcast i8* %103 to %Head* store %Head* %ptrptr71, %Head** %temp70, align 8 %104 = load %Head*, %Head** %temp70, align 8 @@ -555,7 +555,7 @@ noerr_block69: ; preds = %if.exit67 br i1 %not72, label %if.then73, label %if.exit74 if.then73: ; preds = %noerr_block69 - store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var58, align 8 + store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var58, align 8 br label %guard_block75 if.exit74: ; preds = %noerr_block69 @@ -683,7 +683,7 @@ entry: br i1 %not, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint ([1 x i8*]* @"test.TitleResult$elements" to i64) + ret i64 ptrtoint (i8* @test.TitleResult.TITLE_MISSING to i64) if.exit: ; preds = %entry %5 = getelementptr inbounds %Doc, %Doc* %doc, i32 0, i32 0 @@ -696,7 +696,7 @@ if.exit: ; preds = %entry br i1 %not1, label %if.then2, label %if.exit3 if.then2: ; preds = %if.exit - ret i64 ptrtoint ([1 x i8*]* @"test.TitleResult$elements" to i64) + ret i64 ptrtoint (i8* @test.TitleResult.TITLE_MISSING to i64) if.exit3: ; preds = %if.exit %10 = load %"char[]"*, %"char[]"** %head, align 8 @@ -770,21 +770,21 @@ entry: switch.entry: ; preds = %entry %1 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 ptrtoint ([1 x i8*]* @"test.TitleResult$elements" to i64), %1 + %eq = icmp eq i64 ptrtoint (i8* @test.TitleResult.TITLE_MISSING to i64), %1 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.9, i32 0, i32 0) next_if: ; preds = %switch.entry - %eq1 = icmp eq i64 ptrtoint ([2 x i8*]* @"test.ReadError$elements" to i64), %1 + %eq1 = icmp eq i64 ptrtoint (i8* @test.ReadError.BAD_READ to i64), %1 br i1 %eq1, label %switch.case2, label %next_if3 switch.case2: ; preds = %next_if ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.10, i32 0, i32 0) next_if3: ; preds = %next_if - %eq4 = icmp eq i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), %1 + %eq4 = icmp eq i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), %1 br i1 %eq4, label %switch.case5, label %next_if6 switch.case5: ; preds = %next_if3 diff --git a/test/test_suite/errors/failable_inits.c3t b/test/test_suite/errors/failable_inits.c3t index 10d875232..c531dd197 100644 --- a/test/test_suite/errors/failable_inits.c3t +++ b/test/test_suite/errors/failable_inits.c3t @@ -39,7 +39,8 @@ entry: %x.f = alloca i64, align 8 %y = alloca %Bar, align 4 %error_var = alloca i64, align 8 - store i64 ptrtoint ([2 x i8*]* @"test.Foo$elements" to i64), i64* %x.f, align 8 + %reterr = alloca i64, align 8 + store i64 ptrtoint (i8* @test.Foo.MY_VAL1 to i64), i64* %x.f, align 8 %0 = load i64, i64* %x.f, align 8 %not_err = icmp eq i64 %0, 0 br i1 %not_err, label %after_check, label %error @@ -68,6 +69,7 @@ entry: %x.f = alloca i64, align 8 %y = alloca %Bar, align 4 %error_var = alloca i64, align 8 + %reterr = alloca i64, align 8 %0 = bitcast %Bar* %x to i32* store i32 0, i32* %0, align 4 store i64 0, i64* %x.f, align 8 diff --git a/test/test_suite/errors/failable_taddr_and_access.c3t b/test/test_suite/errors/failable_taddr_and_access.c3t index d59748637..914739ced 100644 --- a/test/test_suite/errors/failable_taddr_and_access.c3t +++ b/test/test_suite/errors/failable_taddr_and_access.c3t @@ -27,9 +27,9 @@ fn void main() %Foo = type { i32, i32 } -@introspect.Foo = linkonce constant i8 1 -@"test.MyErr$elements" = linkonce constant [1 x i8*] zeroinitializer -@introspect.MyErr = linkonce constant i8 1 +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@test.MyErr.FOO = linkonce constant i8 1, align 1 +@.typeid.test.MyErr = linkonce constant { i8, i64, [1 x i64] } { i8 9, i64 1, [1 x i64] [i64 ptrtoint (i8* @test.MyErr.FOO to i64)] }, align 8 @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 @.str.1 = private unnamed_addr constant [17 x i8] c"Not visible: %d\0A\00", align 1 @@ -78,7 +78,7 @@ after_check2: ; preds = %after_assign br label %voiderr voiderr: ; preds = %after_check2, %after_assign - store i64 ptrtoint ([1 x i8*]* @"test.MyErr$elements" to i64), i64* %z.f, align 8 + store i64 ptrtoint (i8* @test.MyErr.FOO to i64), i64* %z.f, align 8 br label %voiderr3 voiderr3: ; preds = %voiderr diff --git a/test/test_suite/errors/general_error_regression.c3t b/test/test_suite/errors/general_error_regression.c3t index 7a9b687dc..bb77c7bec 100644 --- a/test/test_suite/errors/general_error_regression.c3t +++ b/test/test_suite/errors/general_error_regression.c3t @@ -70,7 +70,7 @@ fn void main() a.hello(); } -// #expect: foo.ll +/* #expect: foo.ll define void @foo.Foo__hello(i64* %0) #0 { entry: @@ -98,8 +98,8 @@ entry: %z = alloca i64, align 8 %b = alloca i32, align 4 %a = alloca i32, align 4 - store i64 ptrtoint ([5 x i8*]* @"foo.Foo$elements" to i64), i64* %f, align 8 - store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 1) to i64), i64* %ef, align 8 + store i64 ptrtoint (i8* @foo.Foo.X to i64), i64* %f, align 8 + store i64 ptrtoint (i8* @foo.Foo.Y to i64), i64* %ef, align 8 %0 = load i64, i64* %f, align 8 store i64 %0, i64* %x, align 8 %1 = load i64, i64* %x, align 8 @@ -112,22 +112,22 @@ entry: store i64 %5, i64* %z, align 8 %6 = load i64, i64* %z, align 8 %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0), i64 %6) - store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 3) to i64), i64* %x, align 8 + store i64 ptrtoint (i8* @foo.Foo.W to i64), i64* %x, align 8 %8 = load i64, i64* %x, align 8 store i64 %8, i64* %z, align 8 %9 = load i64, i64* %z, align 8 %10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i64 %9) - store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 4) to i64), i64* %x, align 8 + store i64 ptrtoint (i8* @foo.Foo.W1 to i64), i64* %x, align 8 %11 = load i64, i64* %x, align 8 store i64 %11, i64* %z, align 8 %12 = load i64, i64* %z, align 8 %13 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i64 %12) - store i64 ptrtoint ([2 x i8*]* @"foo.Foob$elements" to i64), i64* %x, align 8 + store i64 ptrtoint (i8* @foo.Foob.X1 to i64), i64* %x, align 8 %14 = load i64, i64* %x, align 8 store i64 %14, i64* %z, align 8 %15 = load i64, i64* %z, align 8 %16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0), i64 %15) - store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"foo.Foob$elements", i64 0, i64 1) to i64), i64* %x, align 8 + store i64 ptrtoint (i8* @foo.Foob.Y2 to i64), i64* %x, align 8 %17 = load i64, i64* %x, align 8 store i64 %17, i64* %z, align 8 %18 = load i64, i64* %z, align 8 diff --git a/test/test_suite/errors/macro_err2.c3t b/test/test_suite/errors/macro_err2.c3t index 2eb945e88..0fb55c288 100644 --- a/test/test_suite/errors/macro_err2.c3t +++ b/test/test_suite/errors/macro_err2.c3t @@ -23,7 +23,7 @@ fn void main() define i64 @test.abc(i32* %0) #0 { entry: - ret i64 ptrtoint ([1 x i8*]* @"test.Tester$elements" to i64) + ret i64 ptrtoint (i8* @test.Tester.FOO to i64) } define void @test.main() #0 { diff --git a/test/test_suite/errors/simple_static_failable.c3t b/test/test_suite/errors/simple_static_failable.c3t index a07be7d0f..453c1c024 100644 --- a/test/test_suite/errors/simple_static_failable.c3t +++ b/test/test_suite/errors/simple_static_failable.c3t @@ -13,12 +13,12 @@ fn void main() int! i = Blurg.Y!; } -// #expect: foo.ll +/* #expect: foo.ll define void @foo.main() #0 { entry: %i = alloca i32, align 4 %i.f = alloca i64, align 8 - store i64 ptrtoint ([1 x i8*]* @"foo.Blurg$elements" to i64), i64* %i.f, align 8 + store i64 ptrtoint (i8* @foo.Blurg.Y to i64), i64* %i.f, align 8 ret void } \ No newline at end of file diff --git a/test/test_suite/expressions/pointer_access.c3t b/test/test_suite/expressions/pointer_access.c3t index a7d0a73bf..2188586e0 100644 --- a/test/test_suite/expressions/pointer_access.c3t +++ b/test/test_suite/expressions/pointer_access.c3t @@ -1,4 +1,4 @@ - +// #target: macos-x64 extern fn void printf(char* c, ...); struct ExtraSimple @@ -42,10 +42,10 @@ fn void testSimple() %anon = type { i32, i32 } %anon.0 = type { double } -@introspect.c = linkonce constant i8 1 -@introspect.anon = linkonce constant i8 1 -@introspect.anon.1 = linkonce constant i8 1 -@introspect.ExtraSimple = linkonce constant i8 1 +@.typeid.pointer_access.c = linkonce constant { i8, i64 } { i8 10, i64 5 }, align 8 +@.typeid.pointer_access.anon = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.typeid.pointer_access.anon.1 = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.pointer_access.ExtraSimple = linkonce constant { i8, i64 } { i8 10, i64 6 }, align 8 @.str = private unnamed_addr constant [71 x i8] c"a = %d, c.e = %f, c.f = %f, c.j = %f, g = %d, o0 = %f, r = %d, s = %d\0A\00", align 1 define void @pointer_access.testSimple() #0 { diff --git a/test/test_suite/failable_catch.c3t b/test/test_suite/failable_catch.c3t index e538a8388..f99a05af1 100644 --- a/test/test_suite/failable_catch.c3t +++ b/test/test_suite/failable_catch.c3t @@ -33,144 +33,144 @@ fn int main() define i32 @main() #0 { entry: %a = alloca i32, align 4 - %a.f = alloca i64, align 8 - %x = alloca i32, align 4 - %blockret = alloca i32, align 4 - %b = alloca i32, align 4 - %b.f = alloca i64, align 8 - %x1 = alloca i32, align 4 - %blockret2 = alloca i32, align 4 - %c = alloca i32, align 4 - %c.f = alloca i64, align 8 - %x8 = alloca i32, align 4 - %blockret9 = alloca i32, align 4 - store i32 1, i32* %x, align 4 - %0 = load i32, i32* %x, align 4 - %intbool = icmp ne i32 %0, 0 - br i1 %intbool, label %if.then, label %if.exit + %a.f = alloca i64, align 8 + %x = alloca i32, align 4 + %blockret = alloca i32, align 4 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + %x1 = alloca i32, align 4 + %blockret2 = alloca i32, align 4 + %c = alloca i32, align 4 + %c.f = alloca i64, align 8 + %x8 = alloca i32, align 4 + %blockret9 = alloca i32, align 4 + store i32 1, i32* %x, align 4 + %0 = load i32, i32* %x, align 4 + %intbool = icmp ne i32 %0, 0 + br i1 %intbool, label %if.then, label %if.exit - if.then: ; preds = %entry - %1 = load i32, i32* %x, align 4 - store i32 %1, i32* %blockret, align 4 - br label %expr_block.exit +if.then: ; preds = %entry + %1 = load i32, i32* %x, align 4 + store i32 %1, i32* %blockret, align 4 + br label %expr_block.exit - if.exit: ; preds = %entry - store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %a.f, align 8 - br label %after_assign +if.exit: ; preds = %entry + store i64 ptrtoint (i8* @failable_catch.MyErr.TEST to i64), i64* %a.f, align 8 + br label %after_assign - expr_block.exit: ; preds = %if.then - %2 = load i32, i32* %blockret, align 4 - store i32 %2, i32* %a, align 4 - store i64 0, i64* %a.f, align 8 - br label %after_assign +expr_block.exit: ; preds = %if.then + %2 = load i32, i32* %blockret, align 4 + store i32 %2, i32* %a, align 4 + store i64 0, i64* %a.f, align 8 + br label %after_assign - after_assign: ; preds = %expr_block.exit, %if.exit - %3 = load i64, i64* %a.f, align 8 - %not_err = icmp eq i64 %3, 0 - br i1 %not_err, label %after_check, label %else_block +after_assign: ; preds = %expr_block.exit, %if.exit + %3 = load i64, i64* %a.f, align 8 + %not_err = icmp eq i64 %3, 0 + br i1 %not_err, label %after_check, label %else_block - after_check: ; preds = %after_assign - %4 = load i32, i32* %a, align 4 - %add = add i32 %4, 3 - br label %phi_block +after_check: ; preds = %after_assign + %4 = load i32, i32* %a, align 4 + %add = add i32 %4, 3 + br label %phi_block - else_block: ; preds = %after_assign - br label %phi_block +else_block: ; preds = %after_assign + br label %phi_block - phi_block: ; preds = %else_block, %after_check - %val = phi i32 [ %add, %after_check ], [ 2, %else_block ] - store i32 %val, i32* %x1, align 4 - %5 = load i32, i32* %x1, align 4 - %intbool3 = icmp ne i32 %5, 0 - br i1 %intbool3, label %if.then4, label %if.exit5 +phi_block: ; preds = %else_block, %after_check + %val = phi i32 [ %add, %after_check ], [ 2, %else_block ] + store i32 %val, i32* %x1, align 4 + %5 = load i32, i32* %x1, align 4 + %intbool3 = icmp ne i32 %5, 0 + br i1 %intbool3, label %if.then4, label %if.exit5 - if.then4: ; preds = %phi_block - %6 = load i32, i32* %x1, align 4 - store i32 %6, i32* %blockret2, align 4 - br label %expr_block.exit6 +if.then4: ; preds = %phi_block + %6 = load i32, i32* %x1, align 4 + store i32 %6, i32* %blockret2, align 4 + br label %expr_block.exit6 - if.exit5: ; preds = %phi_block - store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %b.f, align 8 - br label %after_assign7 +if.exit5: ; preds = %phi_block + store i64 ptrtoint (i8* @failable_catch.MyErr.TEST to i64), i64* %b.f, align 8 + br label %after_assign7 - expr_block.exit6: ; preds = %if.then4 - %7 = load i32, i32* %blockret2, align 4 - store i32 %7, i32* %b, align 4 - store i64 0, i64* %b.f, align 8 - br label %after_assign7 +expr_block.exit6: ; preds = %if.then4 + %7 = load i32, i32* %blockret2, align 4 + store i32 %7, i32* %b, align 4 + store i64 0, i64* %b.f, align 8 + br label %after_assign7 - after_assign7: ; preds = %expr_block.exit6, %if.exit5 - store i32 0, i32* %x8, align 4 - %8 = load i32, i32* %x8, align 4 - %intbool10 = icmp ne i32 %8, 0 - br i1 %intbool10, label %if.then11, label %if.exit12 +after_assign7: ; preds = %expr_block.exit6, %if.exit5 + store i32 0, i32* %x8, align 4 + %8 = load i32, i32* %x8, align 4 + %intbool10 = icmp ne i32 %8, 0 + br i1 %intbool10, label %if.then11, label %if.exit12 - if.then11: ; preds = %after_assign7 - %9 = load i32, i32* %x8, align 4 - store i32 %9, i32* %blockret9, align 4 - br label %expr_block.exit13 +if.then11: ; preds = %after_assign7 + %9 = load i32, i32* %x8, align 4 + store i32 %9, i32* %blockret9, align 4 + br label %expr_block.exit13 - if.exit12: ; preds = %after_assign7 - store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %c.f, align 8 - br label %after_assign14 +if.exit12: ; preds = %after_assign7 + store i64 ptrtoint (i8* @failable_catch.MyErr.TEST to i64), i64* %c.f, align 8 + br label %after_assign14 - expr_block.exit13: ; preds = %if.then11 - %10 = load i32, i32* %blockret9, align 4 - store i32 %10, i32* %c, align 4 - store i64 0, i64* %c.f, align 8 - br label %after_assign14 +expr_block.exit13: ; preds = %if.then11 + %10 = load i32, i32* %blockret9, align 4 + store i32 %10, i32* %c, align 4 + store i64 0, i64* %c.f, align 8 + br label %after_assign14 - after_assign14: ; preds = %expr_block.exit13, %if.exit12 - %11 = load i64, i64* %a.f, align 8 - %not_err15 = icmp eq i64 %11, 0 - br i1 %not_err15, label %after_check16, label %voiderr +after_assign14: ; preds = %expr_block.exit13, %if.exit12 + %11 = load i64, i64* %a.f, align 8 + %not_err15 = icmp eq i64 %11, 0 + br i1 %not_err15, label %after_check16, label %voiderr - after_check16: ; preds = %after_assign14 - %12 = load i32, i32* %a, align 4 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 %12) - br label %voiderr +after_check16: ; preds = %after_assign14 + %12 = load i32, i32* %a, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 %12) + br label %voiderr - voiderr: ; preds = %after_check16, %after_assign14 - %13 = load i64, i64* %b.f, align 8 - %not_err17 = icmp eq i64 %13, 0 - br i1 %not_err17, label %after_check18, label %voiderr19 +voiderr: ; preds = %after_check16, %after_assign14 + %13 = load i64, i64* %b.f, align 8 + %not_err17 = icmp eq i64 %13, 0 + br i1 %not_err17, label %after_check18, label %voiderr19 - after_check18: ; preds = %voiderr - %14 = load i32, i32* %b, align 4 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 %14) - br label %voiderr19 +after_check18: ; preds = %voiderr + %14 = load i32, i32* %b, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 %14) + br label %voiderr19 - voiderr19: ; preds = %after_check18, %voiderr - %15 = load i64, i64* %c.f, align 8 - %not_err20 = icmp eq i64 %15, 0 - br i1 %not_err20, label %after_check21, label %voiderr22 +voiderr19: ; preds = %after_check18, %voiderr + %15 = load i64, i64* %c.f, align 8 + %not_err20 = icmp eq i64 %15, 0 + br i1 %not_err20, label %after_check21, label %voiderr22 - after_check21: ; preds = %voiderr19 - %16 = load i32, i32* %c, align 4 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i32 %16) - br label %voiderr22 +after_check21: ; preds = %voiderr19 + %16 = load i32, i32* %c, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i32 %16) + br label %voiderr22 - voiderr22: ; preds = %after_check21, %voiderr19 - %17 = load i64, i64* %c.f, align 8 - %neq = icmp ne i64 %17, 0 - br i1 %neq, label %if.then23, label %if.exit24 +voiderr22: ; preds = %after_check21, %voiderr19 + %17 = load i64, i64* %c.f, align 8 + %neq = icmp ne i64 %17, 0 + br i1 %neq, label %if.then23, label %if.exit24 - if.then23: ; preds = %voiderr22 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0)) - br label %if.exit24 +if.then23: ; preds = %voiderr22 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0)) + br label %if.exit24 - if.exit24: ; preds = %if.then23, %voiderr22 - store i32 3, i32* %c, align 4 - store i64 0, i64* %c.f, align 8 - %18 = load i64, i64* %c.f, align 8 - %not_err25 = icmp eq i64 %18, 0 - br i1 %not_err25, label %after_check26, label %voiderr27 +if.exit24: ; preds = %if.then23, %voiderr22 + store i32 3, i32* %c, align 4 + store i64 0, i64* %c.f, align 8 + %18 = load i64, i64* %c.f, align 8 + %not_err25 = icmp eq i64 %18, 0 + br i1 %not_err25, label %after_check26, label %voiderr27 - after_check26: ; preds = %if.exit24 - %19 = load i32, i32* %c, align 4 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.4, i32 0, i32 0), i32 %19) - br label %voiderr27 +after_check26: ; preds = %if.exit24 + %19 = load i32, i32* %c, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.4, i32 0, i32 0), i32 %19) + br label %voiderr27 - voiderr27: ; preds = %after_check26, %if.exit24 - ret i32 0 - } +voiderr27: ; preds = %after_check26, %if.exit24 + ret i32 0 +} diff --git a/test/test_suite/from_docs/examples_forswitch.c3t b/test/test_suite/from_docs/examples_forswitch.c3t index dc9aba118..c6f292503 100644 --- a/test/test_suite/from_docs/examples_forswitch.c3t +++ b/test/test_suite/from_docs/examples_forswitch.c3t @@ -1,7 +1,7 @@ // #target: macos-x64 module examples; import libc; -import std; +import std::io; fn void example_for() { @@ -110,7 +110,7 @@ loop.body: ; preds = %loop.cond br label %loop.cond loop.exit: ; preds = %loop.cond - call void @"std::builtin.panic"(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.zstr.2, i64 0, i64 0), i32 14) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.zstr.2, i64 0, i64 0), i32 14) unreachable unreachable_block: ; No predecessors! diff --git a/test/test_suite/from_docs/examples_if_catch.c3t b/test/test_suite/from_docs/examples_if_catch.c3t index e09229588..b89e06c48 100644 --- a/test/test_suite/from_docs/examples_if_catch.c3t +++ b/test/test_suite/from_docs/examples_if_catch.c3t @@ -54,7 +54,7 @@ entry: br i1 %eq, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint ([1 x i8*]* @"demo.MathError$elements" to i64) + ret i64 ptrtoint (i8* @demo.MathError.DIVISION_BY_ZERO to i64) if.exit: ; preds = %entry %sifp = sitofp i32 %1 to double @@ -114,7 +114,6 @@ after.errcheck: ; preds = %entry br label %after_assign after_assign: ; preds = %after.errcheck, %error - store i64 0, i64* %err, align 8 br label %testblock testblock: ; preds = %after_assign @@ -141,7 +140,7 @@ if.then: ; preds = %end_block switch.entry: ; preds = %if.then %6 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 ptrtoint ([1 x i8*]* @"demo.MathError$elements" to i64), %6 + %eq = icmp eq i64 ptrtoint (i8* @demo.MathError.DIVISION_BY_ZERO to i64), %6 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry diff --git a/test/test_suite/functions/test_regression.c3t b/test/test_suite/functions/test_regression.c3t index 83e9eb69e..257269c01 100644 --- a/test/test_suite/functions/test_regression.c3t +++ b/test/test_suite/functions/test_regression.c3t @@ -234,8 +234,8 @@ fn Type getValue(Blob blob) /* #expect: test.ll -%Blob.0 = type { i32 } -%Blob.1 = type { double } +%Blob = type { i32 } +%Blob.0 = type { double } %Foo2 = type { i32 } %Bobo = type { i16, float, i16, i16, float, i16 } %"int[]" = type { i32*, i64 } @@ -244,6 +244,13 @@ fn Type getValue(Blob blob) %List = type { i64, i64, i32* } %Foo = type { i32, i32 } +@.typeid.test.Bobo = linkonce constant { i8, i64 } { i8 10, i64 6 }, align 8 +@.typeid.test.Blob = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.typeid.test.Foor = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.test.Foo2 = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8 +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.typeid.test.MyEnum = linkonce constant { i8, i64, i64 } { i8 8, i64 3, i64 0 }, align 8 + define void @test.Foo2__printme(%Foo2* %0) #0 { entry: %1 = getelementptr inbounds %Foo2, %Foo2* %0, i32 0, i32 0 @@ -432,8 +439,8 @@ entry: %elements = alloca i32, align 4 %array = alloca %List, align 8 %i1 = alloca i32, align 4 - %a = alloca %Blob.0, align 4 - %b = alloca %Blob.1, align 8 + %a = alloca %Blob, align 4 + %b = alloca %Blob.0, align 8 %tempcoerce = alloca double, align 8 %ddx = alloca %Foo, align 4 %fro = alloca i32, align 4 @@ -515,15 +522,15 @@ loop.body5: ; preds = %loop.cond2 loop.exit8: ; preds = %loop.cond2 call void @"std::array::list.int.List__free"(%List* %array) - %21 = bitcast %Blob.0* %a to i8* - call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob.0* @.__const.6 to i8*), i32 4, i1 false) - %22 = bitcast %Blob.1* %b to i8* - call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.1* @.__const.7 to i8*), i32 8, i1 false) - %23 = getelementptr inbounds %Blob.0, %Blob.0* %a, i32 0, i32 0 + %21 = bitcast %Blob* %a to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob* @.__const.6 to i8*), i32 4, i1 false) + %22 = bitcast %Blob.0* %b to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.0* @.__const.7 to i8*), i32 8, i1 false) + %23 = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0 %24 = load i32, i32* %23, align 4 %25 = call i32 @test2.int.getValue(i32 %24) %26 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %25) - %27 = getelementptr inbounds %Blob.1, %Blob.1* %b, i32 0, i32 0 + %27 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0 %28 = bitcast double* %tempcoerce to i8* %29 = bitcast double* %27 to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %28, i8* align 8 %29, i32 8, i1 false) diff --git a/test/test_suite/functions/test_regression_mingw.c3t b/test/test_suite/functions/test_regression_mingw.c3t index 85cef878c..d90470154 100644 --- a/test/test_suite/functions/test_regression_mingw.c3t +++ b/test/test_suite/functions/test_regression_mingw.c3t @@ -236,8 +236,8 @@ fn Type getValue(Blob blob) /* #expect: test.ll -%Blob.0 = type { i32 } -%Blob.1 = type { double } +%Blob = type { i32 } +%Blob.0 = type { double } %Foo2 = type { i32 } %Bobo = type { i16, float, i16, i16, float, i16 } %"int[]" = type { i32*, i64 } @@ -246,21 +246,24 @@ fn Type getValue(Blob blob) %List = type { i64, i64, i32* } %Foo = type { i32, i32 } -$introspect.Bobo = comdat any +$.typeid.test.Bobo = comdat any -$introspect.Blob = comdat any +$.typeid.test.Blob = comdat any -$introspect.Foor = comdat any +$.typeid.test.Foor = comdat any -$introspect.Foo2 = comdat any +$.typeid.test.Foo2 = comdat any -$introspect.Foo = comdat any +$.typeid.test.Foo = comdat any -@introspect.Bobo = linkonce constant i8 1, comdat -@introspect.Blob = linkonce constant i8 1, comdat -@introspect.Foor = linkonce constant i8 1, comdat -@introspect.Foo2 = linkonce constant i8 1, comdat -@introspect.Foo = linkonce constant i8 1, comdat +$.typeid.test.MyEnum = comdat any + +@.typeid.test.Bobo = linkonce constant { i8, i64 } { i8 10, i64 6 }, comdat, align 8 +@.typeid.test.Blob = linkonce constant { i8, i64 } { i8 10, i64 2 }, comdat, align 8 +@.typeid.test.Foor = linkonce constant { i8, i64 } { i8 11, i64 2 }, comdat, align 8 +@.typeid.test.Foo2 = linkonce constant { i8, i64 } { i8 10, i64 1 }, comdat, align 8 +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, comdat, align 8 +@.typeid.test.MyEnum = linkonce constant { i8, i64, i64 } { i8 8, i64 3, i64 0 }, comdat, align 8 @.str = private unnamed_addr constant [13 x i8] c"helloWorld!\0A\00", align 1 @test_static.x = internal unnamed_addr global i32 1, align 4 @.str.1 = private unnamed_addr constant [16 x i8] c"Test static %d\0A\00", align 1 @@ -269,8 +272,8 @@ $introspect.Foo = comdat any @.str.3 = private unnamed_addr constant [14 x i8] c"Elements: %d\0A\00", align 1 @.str.4 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1 @.str.5 = private unnamed_addr constant [17 x i8] c"Element[%d]: %d\0A\00", align 1 -@.__const.6 = private unnamed_addr constant %Blob.0 { i32 42 }, align 4 -@.__const.7 = private unnamed_addr constant %Blob.1 { double 3.330000e+01 }, align 8 +@.__const.6 = private unnamed_addr constant %Blob { i32 42 }, align 4 +@.__const.7 = private unnamed_addr constant %Blob.0 { double 3.330000e+01 }, align 8 @.str.8 = private unnamed_addr constant [10 x i8] c"a was %d\0A\00", align 1 @.str.9 = private unnamed_addr constant [10 x i8] c"b was %f\0A\00", align 1 @.str.10 = private unnamed_addr constant [17 x i8] c"Mult int was %d\0A\00", align 1 @@ -287,6 +290,7 @@ $introspect.Foo = comdat any @.str.21 = private unnamed_addr constant [12 x i8] c"Foo is: %d\0A\00", align 1 @.str.22 = private unnamed_addr constant [9 x i8] c"Mutating\00", align 1 +; Function Attrs: nounwind define void @test.Foo2__printme(%Foo2* %0) #0 { entry: %1 = getelementptr inbounds %Foo2, %Foo2* %0, i32 0, i32 0 @@ -295,6 +299,7 @@ entry: ret void } +; Function Attrs: nounwind define i32 @test.Foo2__mutate(%Foo2* %0) #0 { entry: %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.22, i32 0, i32 0)) @@ -465,8 +470,8 @@ entry: %elements = alloca i32, align 4 %array = alloca %List, align 8 %i1 = alloca i32, align 4 - %a = alloca %Blob.0, align 4 - %b = alloca %Blob.1, align 8 + %a = alloca %Blob, align 4 + %b = alloca %Blob.0, align 8 %tempcoerce = alloca i64, align 8 %ddx = alloca %Foo, align 4 %fro = alloca i32, align 4 @@ -554,15 +559,15 @@ loop.body5: ; preds = %loop.cond2 loop.exit8: ; preds = %loop.cond2 call void @"std::array::list.int.List__free"(%List* %array) - %21 = bitcast %Blob.0* %a to i8* - call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob.0* @.__const.6 to i8*), i32 4, i1 false) - %22 = bitcast %Blob.1* %b to i8* - call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.1* @.__const.7 to i8*), i32 8, i1 false) - %23 = getelementptr inbounds %Blob.0, %Blob.0* %a, i32 0, i32 0 + %21 = bitcast %Blob* %a to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob* @.__const.6 to i8*), i32 4, i1 false) + %22 = bitcast %Blob.0* %b to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.0* @.__const.7 to i8*), i32 8, i1 false) + %23 = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0 %24 = load i32, i32* %23, align 4 %25 = call i32 @test2.int.getValue(i32 %24) %26 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %25) - %27 = getelementptr inbounds %Blob.1, %Blob.1* %b, i32 0, i32 0 + %27 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0 %28 = bitcast i64* %tempcoerce to i8* %29 = bitcast double* %27 to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %28, i8* align 8 %29, i32 8, i1 false) diff --git a/test/test_suite/functions/typeless_varargs.c3t b/test/test_suite/functions/typeless_varargs.c3t index 50795c13c..722d74864 100644 --- a/test/test_suite/functions/typeless_varargs.c3t +++ b/test/test_suite/functions/typeless_varargs.c3t @@ -22,6 +22,8 @@ fn int main() /* #expect: test.ll +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 + define void @test.retest(i8* %0, i64 %1) #0 { entry: %foo = alloca %"variant[]", align 8 @@ -74,7 +76,7 @@ entry: store i32 1, i32* %taddr, align 4 %0 = bitcast i32* %taddr to i8* %1 = insertvalue %variant undef, i8* %0, 0 - %2 = insertvalue %variant %1, i64 5, 1 + %2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 %3 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots, i64 0, i64 0 store %variant %2, %variant* %3, align 16 %4 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 @@ -91,7 +93,7 @@ entry: store i32 1, i32* %taddr3, align 4 %10 = bitcast i32* %taddr3 to i8* %11 = insertvalue %variant undef, i8* %10, 0 - %12 = insertvalue %variant %11, i64 5, 1 + %12 = insertvalue %variant %11, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 %13 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots2, i64 0, i64 0 store %variant %12, %variant* %13, align 16 %14 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg1, i32 0, i32 1 diff --git a/test/test_suite/import/import_error.c3 b/test/test_suite/import/import_error.c3 index 40eee3519..4be9e0f7c 100644 --- a/test/test_suite/import/import_error.c3 +++ b/test/test_suite/import/import_error.c3 @@ -1,5 +1,5 @@ module test; -import std::mem; +import std::core::mem; import hello_world; // #error: No module named import test; // #error: Importing the current diff --git a/test/test_suite/import/import_works.c3t b/test/test_suite/import/import_works.c3t index 3ef4cdbd9..c524cd8cf 100644 --- a/test/test_suite/import/import_works.c3t +++ b/test/test_suite/import/import_works.c3t @@ -1,3 +1,3 @@ -import std::io, std::mem; +import std::io, std::core::mem; int foo = 1; \ No newline at end of file diff --git a/test/test_suite/initializer_lists/general_tests.c3t b/test/test_suite/initializer_lists/general_tests.c3t index e43b8127c..c554d5556 100644 --- a/test/test_suite/initializer_lists/general_tests.c3t +++ b/test/test_suite/initializer_lists/general_tests.c3t @@ -38,8 +38,8 @@ fn int test() %"int[]" = type { i32*, i64 } %"Bar[]" = type { %Bar*, i64 } -@introspect.Baz = linkonce constant i8 1 -@introspect.Bar = linkonce constant i8 1 +@.typeid.general_tests.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.general_tests.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 @.__const = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8 @test.foo1 = internal unnamed_addr global i32 22, align 4 @.str = private unnamed_addr constant [7 x i8] c"Hello!\00", align 1 diff --git a/test/test_suite/initializer_lists/statics.c3t b/test/test_suite/initializer_lists/statics.c3t index 4ca20b37e..1a43a9687 100644 --- a/test/test_suite/initializer_lists/statics.c3t +++ b/test/test_suite/initializer_lists/statics.c3t @@ -1,6 +1,5 @@ // #target: macos-x64 import std::io; -import std::mem; import libc; union Baz { @@ -36,8 +35,8 @@ fn int main() %Bar = type { i32, i32 } %"Bar[]" = type { %Bar*, i64 } -@introspect.Baz = linkonce constant i8 1, align 1 -@introspect.Bar = linkonce constant i8 1, align 1 +@.typeid.statics.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.statics.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 @.taddr = private global [1 x %Bar] [%Bar { i32 1, i32 2 }], align 8 @test.c = internal unnamed_addr global %"Bar[]" { %Bar* getelementptr inbounds ([1 x %Bar], [1 x %Bar]* @.taddr, i32 0, i32 0), i64 1 }, align 8 @.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 diff --git a/test/test_suite/initializer_lists/subarrays.c3t b/test/test_suite/initializer_lists/subarrays.c3t index 4bd3a93ca..cd7d29be5 100644 --- a/test/test_suite/initializer_lists/subarrays.c3t +++ b/test/test_suite/initializer_lists/subarrays.c3t @@ -1,7 +1,7 @@ // #target: macos-x64 import std::io; -import std::mem; +import std::core::mem; import libc; union Baz { @@ -51,8 +51,8 @@ fn int main() %"int[]" = type { i32*, i64 } %Baz = type { double } -@introspect.Baz = linkonce constant i8 1, align 1 -@introspect.Bar = linkonce constant i8 1, align 1 +@.typeid.subarrays.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.subarrays.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 @.taddr = private global [2 x %Bar] [%Bar { i32 3, i32 4 }, %Bar { i32 8, i32 9 }], align 8 @subarrays.arrbar = local_unnamed_addr global %"Bar[]" { %Bar* getelementptr inbounds ([2 x %Bar], [2 x %Bar]* @.taddr, i32 0, i32 0), i64 2 }, align 8 @.taddr.3 = private global [2 x i32] [i32 1, i32 2], align 4 diff --git a/test/test_suite/macros/userland_bitcast.c3t b/test/test_suite/macros/userland_bitcast.c3t index 16662f6c5..589b9f868 100644 --- a/test/test_suite/macros/userland_bitcast.c3t +++ b/test/test_suite/macros/userland_bitcast.c3t @@ -78,7 +78,7 @@ fn void main() %Foo = type { i16, i8, i8, i16, i16 } -@introspect.Foo = linkonce constant i8 1 +@.typeid.userland_bitcast.Foo = linkonce constant { i8, i64 } { i8 10, i64 5 }, align 8 @.str = private unnamed_addr constant [16 x i8] c"%f => %d => %f\0A\00", align 1 @.str.1 = private unnamed_addr constant [18 x i8] c"%e => %llu => %e\0A\00", align 1 @@ -104,7 +104,6 @@ entry: store i16 %0, i16* %6, align 2 %7 = load %Foo, %Foo* %z, align 2 store %Foo %7, %Foo* %expr, align 2 - store i64 0, i64* %x, align 8 %ptrptr = bitcast %Foo* %expr to i16* store i16* %ptrptr, i16** %b, align 8 %ptrptr1 = bitcast i64* %x to i16* @@ -145,14 +144,6 @@ entry: %i = alloca i64, align 8 %tempcoerce = alloca i32, align 4 store float %0, float* %expr, align 4 - %1 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 0 - store i8 0, i8* %1, align 1 - %2 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 1 - store i8 0, i8* %2, align 1 - %3 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 2 - store i8 0, i8* %3, align 1 - %4 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 3 - store i8 0, i8* %4, align 1 %ptrptr = bitcast float* %expr to i8* store i8* %ptrptr, i8** %b, align 8 %ptrptr1 = bitcast [4 x i8]* %x to i8* @@ -161,30 +152,30 @@ entry: br label %loop.cond loop.cond: ; preds = %loop.body, %entry - %5 = load i64, i64* %i, align 8 - %lt = icmp ult i64 %5, 4 + %1 = load i64, i64* %i, align 8 + %lt = icmp ult i64 %1, 4 br i1 %lt, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond - %6 = load i8*, i8** %to, align 8 + %2 = load i8*, i8** %to, align 8 + %3 = load i64, i64* %i, align 8 + %ptroffset = getelementptr inbounds i8, i8* %2, i64 %3 + %4 = load i8*, i8** %b, align 8 + %5 = load i64, i64* %i, align 8 + %ptroffset2 = getelementptr inbounds i8, i8* %4, i64 %5 + %6 = load i8, i8* %ptroffset2, align 1 + store i8 %6, i8* %ptroffset, align 1 %7 = load i64, i64* %i, align 8 - %ptroffset = getelementptr inbounds i8, i8* %6, i64 %7 - %8 = load i8*, i8** %b, align 8 - %9 = load i64, i64* %i, align 8 - %ptroffset2 = getelementptr inbounds i8, i8* %8, i64 %9 - %10 = load i8, i8* %ptroffset2, align 1 - store i8 %10, i8* %ptroffset, align 1 - %11 = load i64, i64* %i, align 8 - %add = add i64 %11, 1 + %add = add i64 %7, 1 store i64 %add, i64* %i, align 8 br label %loop.cond loop.exit: ; preds = %loop.cond - %12 = bitcast i32* %tempcoerce to i8* - %13 = bitcast [4 x i8]* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %12, i8* align 1 %13, i32 4, i1 false) - %14 = load i32, i32* %tempcoerce, align 4 - ret i32 %14 + %8 = bitcast i32* %tempcoerce to i8* + %9 = bitcast [4 x i8]* %x to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %8, i8* align 1 %9, i32 4, i1 false) + %10 = load i32, i32* %tempcoerce, align 4 + ret i32 %10 } define void @userland_bitcast.main() #0 { @@ -218,7 +209,6 @@ entry: store float 0x4028B4BC60000000, float* %f, align 4 %0 = load float, float* %f, align 4 store float %0, float* %expr, align 4 - store i32 0, i32* %x, align 4 %ptrptr = bitcast float* %expr to i32* store i32* %ptrptr, i32** %b, align 8 store i32* %x, i32** %to, align 8 @@ -249,7 +239,6 @@ loop.exit: ; preds = %loop.cond store i32 %8, i32* %i, align 4 %9 = load i32, i32* %i, align 4 store i32 %9, i32* %expr3, align 4 - store float 0.000000e+00, float* %x4, align 4 store i32* %expr3, i32** %b5, align 8 %ptrptr7 = bitcast float* %x4 to i32* store i32* %ptrptr7, i32** %to6, align 8 @@ -287,7 +276,6 @@ loop.exit15: ; preds = %loop.cond9 store double 1.235300e+268, double* %d, align 8 %21 = load double, double* %d, align 8 store double %21, double* %expr17, align 8 - store i64 0, i64* %x18, align 8 %ptrptr20 = bitcast double* %expr17 to i64* store i64* %ptrptr20, i64** %b19, align 8 store i64* %x18, i64** %to21, align 8 @@ -318,7 +306,6 @@ loop.exit29: ; preds = %loop.cond23 store i64 %29, i64* %l, align 8 %30 = load double, double* %d, align 8 store double %30, double* %expr30, align 8 - store double 0.000000e+00, double* %x31, align 8 %ptrptr33 = bitcast double* %expr30 to i64* store i64* %ptrptr33, i64** %b32, align 8 %ptrptr35 = bitcast double* %x31 to i64* diff --git a/test/test_suite/pointers/subarray_variant_to_ptr.c3t b/test/test_suite/pointers/subarray_variant_to_ptr.c3t index fdf32faef..3547655cf 100644 --- a/test/test_suite/pointers/subarray_variant_to_ptr.c3t +++ b/test/test_suite/pointers/subarray_variant_to_ptr.c3t @@ -26,6 +26,11 @@ fn void main() /* #expect: foo.ll +%variant = type { i8*, i64 } +%"int[]" = type { i32*, i64 } + +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 + define void @foo.test1(i64 %0, i8* %1) #0 { entry: %z = alloca %variant, align 8 @@ -76,7 +81,7 @@ entry: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([2 x i32]* @.__const to i8*), i32 8, i1 false) %1 = bitcast i32* %x to i8* %2 = insertvalue %variant undef, i8* %1, 0 - %3 = insertvalue %variant %2, i64 5, 1 + %3 = insertvalue %variant %2, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %3, %variant* %taddr, align 8 %4 = bitcast %variant* %taddr to { i64, i8* }* %5 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %4, i32 0, i32 0 diff --git a/test/test_suite/safe/deref.c3t b/test/test_suite/safe/deref.c3t new file mode 100644 index 000000000..b6a15156d --- /dev/null +++ b/test/test_suite/safe/deref.c3t @@ -0,0 +1,29 @@ +// #safe: yes +module foo; + +fn void main() +{ + int* x; + int y = *x; +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca i32*, align 8 + %y = alloca i32, align 4 + store i32* null, i32** %x, align 8 + %0 = load i32*, i32** %x, align 8 + %checknull = icmp eq i32* %0, null + br i1 %checknull, label %panic, label %checkok + +panic: ; preds = %entry + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.2, i64 0, i64 0), i32 6) + br label %checkok + +checkok: ; preds = %panic, %entry + %1 = load i32, i32* %0, align 8 + store i32 %1, i32* %y, align 4 + ret void +} diff --git a/test/test_suite/statements/custom_foreach_with_ref.c3t b/test/test_suite/statements/custom_foreach_with_ref.c3t index 96c1f6a38..dce61961d 100644 --- a/test/test_suite/statements/custom_foreach_with_ref.c3t +++ b/test/test_suite/statements/custom_foreach_with_ref.c3t @@ -86,7 +86,7 @@ fn void main() %Foo = type { [3 x i32] } -@introspect.Foo = linkonce constant i8 1 +@.typeid.foo.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8 @.str = private unnamed_addr constant [11 x i8] c"getFields\0A\00", align 1 @.str.1 = private unnamed_addr constant [11 x i8] c"Call made\0A\00", align 1 @.__const = private unnamed_addr constant %Foo { [3 x i32] [i32 1, i32 5, i32 7] }, align 4 diff --git a/test/test_suite/struct/struct_as_value.c3t b/test/test_suite/struct/struct_as_value.c3t index d084dc76d..5b7484e93 100644 --- a/test/test_suite/struct/struct_as_value.c3t +++ b/test/test_suite/struct/struct_as_value.c3t @@ -13,15 +13,14 @@ fn Event test(int x) return x ? foo : bar; } -// #expect: test.ll +/* #expect: test.ll %Event = type { i32 } -@introspect.Event = linkonce constant i8 1 +@.typeid.test.Event = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8 @.__const = private unnamed_addr constant %Event { i32 1 }, align 4 @.__const.1 = private unnamed_addr constant %Event { i32 2 }, align 4 -; Function Attrs: nounwind define i32 @test.test(i32 %0) #0 { entry: %foo = alloca %Event, align 4 diff --git a/test/test_suite/struct/struct_codegen.c3t b/test/test_suite/struct/struct_codegen.c3t index 7414d0ced..34130abc9 100644 --- a/test/test_suite/struct/struct_codegen.c3t +++ b/test/test_suite/struct/struct_codegen.c3t @@ -1,4 +1,4 @@ - +// #target: macos-x64 module test; struct Point @@ -12,11 +12,11 @@ fn void test1() Point p = { 5, 6 }; } -// #expect: test.ll +/* #expect: test.ll %Point = type { i32, i32 } -@introspect.Point = linkonce constant i8 1 +@.typeid.test.Point = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 @.__const = private unnamed_addr constant %Point { i32 5, i32 6 }, align 4 define void @test.test1() #0 { diff --git a/test/test_suite/struct/struct_codegen_empty.c3t b/test/test_suite/struct/struct_codegen_empty.c3t index d9f7cbaa3..bdcc6c909 100644 --- a/test/test_suite/struct/struct_codegen_empty.c3t +++ b/test/test_suite/struct/struct_codegen_empty.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 struct StructA { int a; @@ -20,7 +21,7 @@ fn void test() StructB b3 = { .b = { } }; } -// #expect: struct_codegen_empty.ll +/* #expect: struct_codegen_empty.ll %a = alloca %StructA, align 4 %a2 = alloca %StructA, align 4 diff --git a/test/test_suite/struct/struct_const_construct_simple.c3t b/test/test_suite/struct/struct_const_construct_simple.c3t index a72dcffb9..132bd74ff 100644 --- a/test/test_suite/struct/struct_const_construct_simple.c3t +++ b/test/test_suite/struct/struct_const_construct_simple.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 module structo; struct Foo @@ -21,7 +22,7 @@ private Foo foo8 = FOO7; %Foo = type { i32, i64 } -@introspect.Foo = linkonce constant i8 1 +@.typeid.structo.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 @structo.x = protected unnamed_addr global i64 16, align 8 @structo.foo1 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8 @structo.foo2 = protected unnamed_addr global %Foo { i32 2, i64 0 }, align 8 @@ -30,4 +31,4 @@ private Foo foo8 = FOO7; @structo.foo5 = protected unnamed_addr global %Foo zeroinitializer, align 8 @structo.foo6 = protected unnamed_addr global %Foo zeroinitializer, align 8 @structo.FOO7 = protected unnamed_addr constant %Foo { i32 1, i64 2 }, align 8 -@structo.foo8 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8 +@structo.foo8 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8 \ No newline at end of file diff --git a/test/test_suite/variant/variant_assign.c3t b/test/test_suite/variant/variant_assign.c3t index cdb0a8e64..52d53ea16 100644 --- a/test/test_suite/variant/variant_assign.c3t +++ b/test/test_suite/variant/variant_assign.c3t @@ -58,6 +58,10 @@ fn int main() /* #expect: foo.ll +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 +@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2 +@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1 + define void @foo.test(i64 %0, i8* %1) #0 { entry: %z = alloca %variant, align 8 @@ -76,7 +80,7 @@ entry: switch.entry: ; preds = %entry %6 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 5, %6 + %eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %6 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry @@ -90,7 +94,7 @@ switch.case: ; preds = %switch.entry br label %switch.exit next_if: ; preds = %switch.entry - %eq2 = icmp eq i64 15, %6 + %eq2 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %6 br i1 %eq2, label %switch.case3, label %next_if5 switch.case3: ; preds = %next_if @@ -130,14 +134,14 @@ entry: %4 = bitcast %variant* %anon to i8* %5 = bitcast %variant* %y to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %4, i8* align 8 %5, i32 16, i1 false) - %6 = getelementptr inbounds %variant, %variant* %anon, i32 0, i32 1 + %6 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1 %7 = load i64, i64* %6, align 8 store i64 %7, i64* %switch, align 8 br label %switch.entry switch.entry: ; preds = %entry %8 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 5, %8 + %eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %8 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry @@ -148,7 +152,7 @@ switch.case: ; preds = %switch.entry store i32 12, i32* %taddr, align 4 %12 = bitcast i32* %taddr to i8* %13 = insertvalue %variant undef, i8* %12, 0 - %14 = insertvalue %variant %13, i64 5, 1 + %14 = insertvalue %variant %13, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %14, %variant* %y, align 8 %15 = load i32*, i32** %z, align 8 %16 = load i32, i32* %15, align 8 @@ -156,7 +160,7 @@ switch.case: ; preds = %switch.entry br label %switch.exit next_if: ; preds = %switch.entry - %eq1 = icmp eq i64 15, %8 + %eq1 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %8 br i1 %eq1, label %switch.case2, label %next_if4 switch.case2: ; preds = %next_if @@ -195,14 +199,14 @@ entry: %4 = bitcast %variant* %anon to i8* %5 = bitcast %variant* %y to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %4, i8* align 8 %5, i32 16, i1 false) - %6 = getelementptr inbounds %variant, %variant* %anon, i32 0, i32 1 + %6 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1 %7 = load i64, i64* %6, align 8 store i64 %7, i64* %switch, align 8 br label %switch.entry switch.entry: ; preds = %entry %8 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 5, %8 + %eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %8 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry @@ -216,7 +220,7 @@ switch.case: ; preds = %switch.entry br label %switch.exit next_if: ; preds = %switch.entry - %eq1 = icmp eq i64 15, %8 + %eq1 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %8 br i1 %eq1, label %switch.case2, label %next_if4 switch.case2: ; preds = %next_if @@ -263,7 +267,7 @@ entry: store double 1.230000e+02, double* %taddr, align 8 %0 = bitcast double* %taddr to i8* %1 = insertvalue %variant undef, i8* %0, 0 - %2 = insertvalue %variant %1, i64 15, 1 + %2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1 store %variant %2, %variant* %taddr1, align 8 %3 = bitcast %variant* %taddr1 to { i64, i8* }* %4 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %3, i32 0, i32 0 @@ -274,7 +278,7 @@ entry: store i32 1, i32* %taddr2, align 4 %6 = bitcast i32* %taddr2 to i8* %7 = insertvalue %variant undef, i8* %6, 0 - %8 = insertvalue %variant %7, i64 5, 1 + %8 = insertvalue %variant %7, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %8, %variant* %taddr3, align 8 %9 = bitcast %variant* %taddr3 to { i64, i8* }* %10 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %9, i32 0, i32 0 @@ -284,7 +288,7 @@ entry: call void @foo.test(i64 %lo4, i8* %hi5) store i8 1, i8* %taddr6, align 1 %12 = insertvalue %variant undef, i8* %taddr6, 0 - %13 = insertvalue %variant %12, i64 2, 1 + %13 = insertvalue %variant %12, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1 store %variant %13, %variant* %taddr7, align 8 %14 = bitcast %variant* %taddr7 to { i64, i8* }* %15 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %14, i32 0, i32 0 @@ -295,7 +299,7 @@ entry: store double 1.235000e+02, double* %taddr10, align 8 %17 = bitcast double* %taddr10 to i8* %18 = insertvalue %variant undef, i8* %17, 0 - %19 = insertvalue %variant %18, i64 15, 1 + %19 = insertvalue %variant %18, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1 store %variant %19, %variant* %taddr11, align 8 %20 = bitcast %variant* %taddr11 to { i64, i8* }* %21 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %20, i32 0, i32 0 @@ -306,7 +310,7 @@ entry: store i32 1, i32* %taddr14, align 4 %23 = bitcast i32* %taddr14 to i8* %24 = insertvalue %variant undef, i8* %23, 0 - %25 = insertvalue %variant %24, i64 5, 1 + %25 = insertvalue %variant %24, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %25, %variant* %taddr15, align 8 %26 = bitcast %variant* %taddr15 to { i64, i8* }* %27 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %26, i32 0, i32 0 @@ -316,7 +320,7 @@ entry: call void @foo.test2(i64 %lo16, i8* %hi17) store i8 1, i8* %taddr18, align 1 %29 = insertvalue %variant undef, i8* %taddr18, 0 - %30 = insertvalue %variant %29, i64 2, 1 + %30 = insertvalue %variant %29, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1 store %variant %30, %variant* %taddr19, align 8 %31 = bitcast %variant* %taddr19 to { i64, i8* }* %32 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %31, i32 0, i32 0 @@ -327,7 +331,7 @@ entry: store double 1.240000e+02, double* %taddr22, align 8 %34 = bitcast double* %taddr22 to i8* %35 = insertvalue %variant undef, i8* %34, 0 - %36 = insertvalue %variant %35, i64 15, 1 + %36 = insertvalue %variant %35, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1 store %variant %36, %variant* %taddr23, align 8 %37 = bitcast %variant* %taddr23 to { i64, i8* }* %38 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %37, i32 0, i32 0 @@ -338,7 +342,7 @@ entry: store i32 2, i32* %taddr26, align 4 %40 = bitcast i32* %taddr26 to i8* %41 = insertvalue %variant undef, i8* %40, 0 - %42 = insertvalue %variant %41, i64 5, 1 + %42 = insertvalue %variant %41, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %42, %variant* %taddr27, align 8 %43 = bitcast %variant* %taddr27 to { i64, i8* }* %44 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %43, i32 0, i32 0 @@ -348,7 +352,7 @@ entry: call void @foo.test3(i64 %lo28, i8* %hi29) store i8 1, i8* %taddr30, align 1 %46 = insertvalue %variant undef, i8* %taddr30, 0 - %47 = insertvalue %variant %46, i64 2, 1 + %47 = insertvalue %variant %46, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1 store %variant %47, %variant* %taddr31, align 8 %48 = bitcast %variant* %taddr31 to { i64, i8* }* %49 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %48, i32 0, i32 0 diff --git a/test/test_suite/variant/variant_switch.c3t b/test/test_suite/variant/variant_switch.c3t index 89984f016..d60f444de 100644 --- a/test/test_suite/variant/variant_switch.c3t +++ b/test/test_suite/variant/variant_switch.c3t @@ -30,6 +30,10 @@ fn int main() /* #expect: foo.ll +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 +@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2 +@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1 + define void @foo.test(i64 %0, i8* %1) #0 { entry: %z = alloca %variant, align 8 @@ -48,7 +52,7 @@ entry: switch.entry: ; preds = %entry %6 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 5, %6 + %eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %6 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry @@ -64,7 +68,7 @@ switch.case: ; preds = %switch.entry br label %switch.exit next_if: ; preds = %switch.entry - %eq2 = icmp eq i64 15, %6 + %eq2 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %6 br i1 %eq2, label %switch.case3, label %next_if5 switch.case3: ; preds = %next_if @@ -87,7 +91,7 @@ switch.default: ; preds = %next_if5 switch.exit: ; preds = %switch.default, %switch.case3, %switch.case %18 = getelementptr inbounds %variant, %variant* %z, i32 0, i32 1 %19 = load i64, i64* %18, align 8 - %eq6 = icmp eq i64 %19, 5 + %eq6 = icmp eq i64 %19, ptrtoint ({ i8, i16 }* @.typeid.int to i64) br i1 %eq6, label %if.then, label %if.exit if.then: ; preds = %switch.exit @@ -114,7 +118,7 @@ entry: store double 1.230000e+02, double* %taddr, align 8 %0 = bitcast double* %taddr to i8* %1 = insertvalue %variant undef, i8* %0, 0 - %2 = insertvalue %variant %1, i64 15, 1 + %2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1 store %variant %2, %variant* %taddr1, align 8 %3 = bitcast %variant* %taddr1 to { i64, i8* }* %4 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %3, i32 0, i32 0 @@ -125,7 +129,7 @@ entry: store i32 1, i32* %taddr2, align 4 %6 = bitcast i32* %taddr2 to i8* %7 = insertvalue %variant undef, i8* %6, 0 - %8 = insertvalue %variant %7, i64 5, 1 + %8 = insertvalue %variant %7, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %8, %variant* %taddr3, align 8 %9 = bitcast %variant* %taddr3 to { i64, i8* }* %10 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %9, i32 0, i32 0 @@ -135,7 +139,7 @@ entry: call void @foo.test(i64 %lo4, i8* %hi5) store i8 1, i8* %taddr6, align 1 %12 = insertvalue %variant undef, i8* %taddr6, 0 - %13 = insertvalue %variant %12, i64 2, 1 + %13 = insertvalue %variant %12, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1 store %variant %13, %variant* %taddr7, align 8 %14 = bitcast %variant* %taddr7 to { i64, i8* }* %15 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %14, i32 0, i32 0 diff --git a/test/test_suite/variant/variant_test.c3t b/test/test_suite/variant/variant_test.c3t index af4e75172..db5437959 100644 --- a/test/test_suite/variant/variant_test.c3t +++ b/test/test_suite/variant/variant_test.c3t @@ -67,7 +67,11 @@ fn void main() %variant = type { i8*, i64 } %"variant[]" = type { %variant*, i64 } -@"int*" = weak constant i8 1 +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 +@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2 +@.typeid.variant = linkonce constant { i8 } { i8 7 }, align 1 +@".typeid.int*" = linkonce constant { i8, i64 } { i8 15, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64) }, align 8 +@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1 define void @foo.test(i64 %0, i8* %1) #0 { entry: @@ -85,7 +89,7 @@ entry: switch.entry: ; preds = %entry %6 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 5, %6 + %eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %6 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry @@ -93,7 +97,7 @@ switch.case: ; preds = %switch.entry br label %switch.exit next_if: ; preds = %switch.entry - %eq1 = icmp eq i64 15, %6 + %eq1 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %6 br i1 %eq1, label %switch.case2, label %next_if3 switch.case2: ; preds = %next_if @@ -101,7 +105,7 @@ switch.case2: ; preds = %next_if br label %switch.exit next_if3: ; preds = %next_if - %eq4 = icmp eq i64 17, %6 + %eq4 = icmp eq i64 ptrtoint ({ i8 }* @.typeid.variant to i64), %6 br i1 %eq4, label %switch.case5, label %next_if6 switch.case5: ; preds = %next_if3 @@ -109,7 +113,7 @@ switch.case5: ; preds = %next_if3 br label %switch.exit next_if6: ; preds = %next_if3 - %eq7 = icmp eq i64 ptrtoint (i8* @"int*" to i64), %6 + %eq7 = icmp eq i64 ptrtoint ({ i8, i64 }* @".typeid.int*" to i64), %6 br i1 %eq7, label %switch.case8, label %next_if9 switch.case8: ; preds = %next_if6 @@ -197,12 +201,12 @@ entry: store i32 1, i32* %taddr, align 4 %0 = bitcast i32* %taddr to i8* %1 = insertvalue %variant undef, i8* %0, 0 - %2 = insertvalue %variant %1, i64 5, 1 + %2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %2, %variant* %x, align 8 store i32 0, i32* %z, align 4 %3 = bitcast i32* %z to i8* %4 = insertvalue %variant undef, i8* %3, 0 - %5 = insertvalue %variant %4, i64 5, 1 + %5 = insertvalue %variant %4, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %5, %variant* %y, align 8 %6 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1 %7 = load i64, i64* %6, align 8 @@ -212,7 +216,7 @@ entry: store i64 %9, i64* %h, align 8 %10 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1 %11 = load i64, i64* %10, align 8 - %eq = icmp eq i64 %11, 5 + %eq = icmp eq i64 %11, ptrtoint ({ i8, i16 }* @.typeid.int to i64) br i1 %eq, label %if.then, label %if.exit if.then: ; preds = %entry @@ -222,7 +226,7 @@ if.then: ; preds = %entry if.exit: ; preds = %if.then, %entry %12 = getelementptr inbounds %variant, %variant* %x, i32 0, i32 1 %13 = load i64, i64* %12, align 8 - %eq1 = icmp eq i64 %13, 5 + %eq1 = icmp eq i64 %13, ptrtoint ({ i8, i16 }* @.typeid.int to i64) br i1 %eq1, label %if.then2, label %if.exit3 if.then2: ; preds = %if.exit @@ -233,15 +237,15 @@ if.exit3: ; preds = %if.then2, %if.exit store double 1.000000e+00, double* %taddr4, align 8 %14 = bitcast double* %taddr4 to i8* %15 = insertvalue %variant undef, i8* %14, 0 - %16 = insertvalue %variant %15, i64 15, 1 + %16 = insertvalue %variant %15, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1 store %variant %16, %variant* %y, align 8 %17 = bitcast %variant* %x to i8* %18 = insertvalue %variant undef, i8* %17, 0 - %19 = insertvalue %variant %18, i64 17, 1 + %19 = insertvalue %variant %18, i64 ptrtoint ({ i8 }* @.typeid.variant to i64), 1 store %variant %19, %variant* %x, align 8 %20 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1 %21 = load i64, i64* %20, align 8 - %eq5 = icmp eq i64 %21, 5 + %eq5 = icmp eq i64 %21, ptrtoint ({ i8, i16 }* @.typeid.int to i64) br i1 %eq5, label %if.then6, label %if.exit7 if.then6: ; preds = %if.exit3 @@ -251,7 +255,7 @@ if.then6: ; preds = %if.exit3 if.exit7: ; preds = %if.then6, %if.exit3 %22 = getelementptr inbounds %variant, %variant* %x, i32 0, i32 1 %23 = load i64, i64* %22, align 8 - %eq8 = icmp eq i64 %23, 5 + %eq8 = icmp eq i64 %23, ptrtoint ({ i8, i16 }* @.typeid.int to i64) br i1 %eq8, label %if.then9, label %if.exit10 if.then9: ; preds = %if.exit7 @@ -268,7 +272,7 @@ if.exit10: ; preds = %if.then9, %if.exit7 store double 1.000000e+00, double* %taddr11, align 8 %27 = bitcast double* %taddr11 to i8* %28 = insertvalue %variant undef, i8* %27, 0 - %29 = insertvalue %variant %28, i64 15, 1 + %29 = insertvalue %variant %28, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1 store %variant %29, %variant* %taddr12, align 8 %30 = bitcast %variant* %taddr12 to { i64, i8* }* %31 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %30, i32 0, i32 0 @@ -279,7 +283,7 @@ if.exit10: ; preds = %if.then9, %if.exit7 store i32 1, i32* %taddr15, align 4 %33 = bitcast i32* %taddr15 to i8* %34 = insertvalue %variant undef, i8* %33, 0 - %35 = insertvalue %variant %34, i64 5, 1 + %35 = insertvalue %variant %34, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1 store %variant %35, %variant* %taddr16, align 8 %36 = bitcast %variant* %taddr16 to { i64, i8* }* %37 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %36, i32 0, i32 0 @@ -289,7 +293,7 @@ if.exit10: ; preds = %if.then9, %if.exit7 call void @foo.test(i64 %lo17, i8* %hi18) store i8 1, i8* %taddr19, align 1 %39 = insertvalue %variant undef, i8* %taddr19, 0 - %40 = insertvalue %variant %39, i64 2, 1 + %40 = insertvalue %variant %39, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1 store %variant %40, %variant* %taddr20, align 8 %41 = bitcast %variant* %taddr20 to { i64, i8* }* %42 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %41, i32 0, i32 0 @@ -310,17 +314,17 @@ if.exit10: ; preds = %if.then9, %if.exit7 store double 1.000000e+00, double* %taddr23, align 8 %50 = bitcast double* %taddr23 to i8* %51 = insertvalue %variant undef, i8* %50, 0 - %52 = insertvalue %variant %51, i64 15, 1 + %52 = insertvalue %variant %51, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1 %53 = getelementptr inbounds [5 x %variant], [5 x %variant]* %varargslots, i64 0, i64 2 store %variant %52, %variant* %53, align 16 %54 = bitcast %variant* %x to i8* %55 = insertvalue %variant undef, i8* %54, 0 - %56 = insertvalue %variant %55, i64 17, 1 + %56 = insertvalue %variant %55, i64 ptrtoint ({ i8 }* @.typeid.variant to i64), 1 %57 = getelementptr inbounds [5 x %variant], [5 x %variant]* %varargslots, i64 0, i64 3 store %variant %56, %variant* %57, align 16 %58 = bitcast i32** %df to i8* %59 = insertvalue %variant undef, i8* %58, 0 - %60 = insertvalue %variant %59, i64 ptrtoint (i8* @"int*" to i64), 1 + %60 = insertvalue %variant %59, i64 ptrtoint ({ i8, i64 }* @".typeid.int*" to i64), 1 %61 = getelementptr inbounds [5 x %variant], [5 x %variant]* %varargslots, i64 0, i64 4 store %variant %60, %variant* %61, align 16 %62 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 diff --git a/test/test_suite/vector/vector_ops2.c3t b/test/test_suite/vector/vector_ops2.c3t index 79b4f8fb6..02b6fb00e 100644 --- a/test/test_suite/vector/vector_ops2.c3t +++ b/test/test_suite/vector/vector_ops2.c3t @@ -149,7 +149,7 @@ entry: br i1 %zero, label %panic, label %checkok panic: ; preds = %entry - call void @"std::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.2, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.3, i64 0, i64 0), i32 12) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.2, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.3, i64 0, i64 0), i32 12) br label %checkok checkok: ; preds = %panic, %entry @@ -433,7 +433,7 @@ entry: br i1 %zero, label %panic, label %checkok panic: ; preds = %entry - call void @"std::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr.20, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.21, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.22, i64 0, i64 0), i32 56) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr.20, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.21, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.22, i64 0, i64 0), i32 56) br label %checkok checkok: ; preds = %panic, %entry @@ -468,7 +468,7 @@ checkok: ; preds = %panic, %entry br i1 %shift_underflow, label %panic1, label %checkok2 panic1: ; preds = %checkok - call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.25, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.26, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.27, i64 0, i64 0), i32 60) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.25, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.26, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.27, i64 0, i64 0), i32 60) br label %checkok2 checkok2: ; preds = %panic1, %checkok @@ -477,7 +477,7 @@ checkok2: ; preds = %panic1, %checkok br i1 %shift_exceeds, label %panic3, label %checkok4 panic3: ; preds = %checkok2 - call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.28, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.29, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.30, i64 0, i64 0), i32 60) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.28, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.29, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.30, i64 0, i64 0), i32 60) br label %checkok4 checkok4: ; preds = %panic3, %checkok2 @@ -500,7 +500,7 @@ checkok4: ; preds = %panic3, %checkok2 br i1 %shift_underflow5, label %panic6, label %checkok7 panic6: ; preds = %checkok4 - call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.32, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.33, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.34, i64 0, i64 0), i32 62) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.32, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.33, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.34, i64 0, i64 0), i32 62) br label %checkok7 checkok7: ; preds = %panic6, %checkok4 @@ -509,7 +509,7 @@ checkok7: ; preds = %panic6, %checkok4 br i1 %shift_exceeds8, label %panic9, label %checkok10 panic9: ; preds = %checkok7 - call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.35, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.36, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.37, i64 0, i64 0), i32 62) + call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.35, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.36, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.37, i64 0, i64 0), i32 62) br label %checkok10 checkok10: ; preds = %panic9, %checkok7 diff --git a/test/test_suite2/abi/aarch64_args.c3t b/test/test_suite2/abi/aarch64_args.c3t new file mode 100644 index 000000000..2de1b44db --- /dev/null +++ b/test/test_suite2/abi/aarch64_args.c3t @@ -0,0 +1,29 @@ +// #target: macos-aarch64 +module test; + +struct Large { + void*[8] pointers; +} + +extern fn void pass_large(Large); + +fn void example() { + Large l = {}; + pass_large(l); + pass_large(l); +} + +/* #expect: test.ll + +define void @test.example() #0 { +entry: + %l = alloca %Large, align 8 + %indirectarg = alloca %Large, align 8 + %indirectarg1 = alloca %Large, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %l, i8 0, i64 64, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %l, i32 64, i1 false) + call void @pass_large(ptr align 8 %indirectarg) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg1, ptr align 8 %l, i32 64, i1 false) + call void @pass_large(ptr align 8 %indirectarg1) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/abi/aarch64_hfa_args.c3t b/test/test_suite2/abi/aarch64_hfa_args.c3t new file mode 100644 index 000000000..7a3522e1b --- /dev/null +++ b/test/test_suite2/abi/aarch64_hfa_args.c3t @@ -0,0 +1,32 @@ +// #target: macos-aarch64 +module test; +define Int8x16 = ichar[<16>]; +define Float32x3 = float[<3>]; + +struct HFAv3 +{ + Float32x3[4] arr; +} + +struct MixedHFAv3 +{ + Float32x3[3] arr; + Int8x16 b; +} + +fn HFAv3 test(HFAv3 a0, HFAv3 a1, HFAv3 a2) { + return a2; +} + +fn MixedHFAv3 test_mixed(MixedHFAv3 a0, MixedHFAv3 a1, MixedHFAv3 a2) { + return a2; +} + +/* #expect: test.ll + + +%HFAv3 = type { [4 x <3 x float>] } +%MixedHFAv3 = type { [3 x <3 x float>], <16 x i8> } + +define %HFAv3 @test.test([4 x <4 x float>] %0, [4 x <4 x float>] %1, [4 x <4 x float>] %2) +define %MixedHFAv3 @test.test_mixed([4 x <4 x float>] %0, [4 x <4 x float>] %1, [4 x <4 x float>] %2) #0 { diff --git a/test/test_suite2/abi/darwin64_avx.c3t b/test/test_suite2/abi/darwin64_avx.c3t new file mode 100644 index 000000000..b8f843816 --- /dev/null +++ b/test/test_suite2/abi/darwin64_avx.c3t @@ -0,0 +1,141 @@ +// #target: macos-x64 +// #opt: --x86vec=avx +module test; + +define Mm256 = float[<8>]; +struct St256 { + Mm256 m; +} + +St256 x38; +Mm256 x37; + +extern fn void f38(St256 x); +extern fn void f37(Mm256 x); +fn void f39() { f38(x38); f37(x37); } + +// The two next tests make sure that the struct below is passed +// in the same way regardless of avx being used + +// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16) + +define Mm128 = float[<4>]; +struct Two128 { + Mm128 m; + Mm128 n; +} + +extern fn void func40(Two128 s); +fn void func41(Two128 s) { + func40(s); +} + +struct Atwo128 { + Mm128[2] array; +} + +struct Sa { + Atwo128 x; +} + +extern fn void func42(Sa s); +fn void func43(Sa s) { + func42(s); +} + + +define Vec46 = float[<2>]; +extern fn void f46(Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46); +fn void test46() { Vec46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); } + +struct Vec47 { uint a; } +extern fn void f47(int,int,int,int,int,int,Vec47); +fn void test47(int a, Vec47 b) { f47(a, a, a, a, a, a, b); } + +fn void test49_helper(double, ...); +fn void test49(double d, double e) { test49_helper(d, e); } + +struct Complex { double i; double c; } +extern fn void test52_helper(int, ...); +Mm256 x52; +fn void test52() { + test52_helper(0, x52, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 }); +} + +extern fn void test54_helper(Mm256, ...); +Mm256 x54; +fn void test54() { + test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 }); + test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 }); +} + +define Mm512 = float[<16>]; +struct St512 { + Mm512 m; +} + +St512 x55; +Mm512 x56; + +extern fn void f55(St512 x); + +extern fn void f56(Mm512 x); +fn void f57() { f55(x55); f56(x56); } + +struct Two256 { + Mm256 m; + Mm256 n; +} + +extern fn void f58(Two256 s); +fn void f59(Two256 s) { + f58(s); +} + +struct Atwo256 { + Mm256[2] array; +} + +struct SAtwo256 { + Atwo256 x; +} + +extern fn void f60(SAtwo256 s); +fn void f61(SAtwo256 s) { + f60(s); +} + + +/* #expect: test.ll + +declare void @f38(<8 x float>) +declare void @f37(<8 x float>) + +declare void @func40(ptr byval(%Two128) align 16) +define void @test.func41(ptr byval(%Two128) align 16 %0) + +declare void @func42(ptr byval(%Sa) align 16) +define void @test.func43(ptr byval(%Sa) align 16 %0) + +declare void @f46(double, double, double, double, double, double, double, double, ptr byval(<2 x float>) align 8, ptr byval(<2 x float>) align 8) #0 +declare void @f47(i32, i32, i32, i32, i32, i32, i32) + +declare void @test.test49_helper(double, ...) +define void @test.test49(double %0, double %1) +entry: + call void (double, ...) @test.test49_helper(double %0, double %1) + ret void + + call void (i32, ...) @test52_helper(i32 0, <8 x float> %0, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi) + call void (<8 x float>, ...) @test54_helper(<8 x float> %0, <8 x float> %1, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi) + call void (<8 x float>, ...) @test54_helper(<8 x float> %6, <8 x float> %7, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, ptr byval(%Complex) align 8 %indirectarg) + +declare void @f55(ptr byval(%St512) align 64) +declare void @f56(ptr byval(<16 x float>) align 64) + +declare void @f58(ptr byval(%Two256) align 32) +define void @test.f59(ptr byval(%Two256) align 32 %0) + +declare void @f60(ptr byval(%SAtwo256) align 32) + +define void @test.f61(ptr byval(%SAtwo256) align 32 %0) #0 { diff --git a/test/test_suite2/abi/darwin64_avx512.c3t b/test/test_suite2/abi/darwin64_avx512.c3t new file mode 100644 index 000000000..ee2afdce5 --- /dev/null +++ b/test/test_suite2/abi/darwin64_avx512.c3t @@ -0,0 +1,74 @@ +// #target: macos-x64 +// #opt: --x86vec=avx512 +module test; + +define Mm256 = float[<8>]; +define Mm512 = float[<16>]; +struct St512 { + Mm512 m; +} + +St512 x55; +Mm512 x56; + +extern fn void f55(St512 x); + +extern fn void f56(Mm512 x); +fn void f57() { f55(x55); f56(x56); } + +struct Two256 { + Mm256 m; + Mm256 n; +} + +extern fn void f58(Two256 s); +fn void f59(Two256 s) { + f58(s); +} + +struct Atwo256 { + Mm256[2] array; +} + +struct SAtwo256 { + Atwo256 x; +} + +extern fn void f60(SAtwo256 s); +fn void f61(SAtwo256 s) { + f60(s); +} + +struct Complex { double i; double c; } + +// AVX512: @f62_helper(i32 0, <16 x float> {{%[a-zA-Z0-9]+}}, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double {{%[a-zA-Z0-9]+}}, double {{%[a-zA-Z0-9]+}}) +fn void f62_helper(int, ...); +Mm512 x62; +fn void f62() { + f62_helper(0, x62, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 1.0, 1.0 }); +} + +fn void f64_helper(Mm512, ...); +Mm512 x64; +fn void f64() { + f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 1.0, 1.0 }); + f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 1.0, 1.0 }); +} + + +/* #expect: test.ll + +declare void @f55(<16 x float>) #0 +declare void @f56(<16 x float>) #0 + +declare void @f58(ptr byval(%Two256) align 32) #0 +define void @test.f59(ptr byval(%Two256) align 32 %0) #0 { + +declare void @f60(ptr byval(%SAtwo256) align 32) #0 +define void @test.f61(ptr byval(%SAtwo256) align 32 %0) #0 { + +define void @test.f62() #0 { + call void (i32, ...) @test.f62_helper(i32 0, <16 x float> %0, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi) +define void @test.f64() #0 { + call void (<16 x float>, ...) @test.f64_helper(<16 x float> %0, <16 x float> %1, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi) + call void (<16 x float>, ...) @test.f64_helper(<16 x float> %6, <16 x float> %7, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, ptr byval(%Complex) align 8 %indirectarg) diff --git a/test/test_suite2/abi/darwin64_sse.c3t b/test/test_suite2/abi/darwin64_sse.c3t new file mode 100644 index 000000000..a13b9bf04 --- /dev/null +++ b/test/test_suite2/abi/darwin64_sse.c3t @@ -0,0 +1,56 @@ +// #target: macos-x64 +// #opt: --x86vec=sse +module test; + +define Mm256 = float[<8>]; +struct St256 { + Mm256 m; +} + +St256 x38; +Mm256 x37; + +extern fn void f38(St256 x); +extern fn void f37(Mm256 x); +fn void f39() { f38(x38); f37(x37); } + +// The two next tests make sure that the struct below is passed +// in the same way regardless of avx being used + +// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16) + +define Mm128 = float[<4>]; +struct Two128 { + Mm128 m; + Mm128 n; +} + +extern fn void func40(Two128 s); +fn void func41(Two128 s) { + func40(s); +} + +struct Atwo128 { + Mm128[2] array; +} + +struct Sa { + Atwo128 x; +} + +extern fn void func42(Sa s); +fn void func43(Sa s) { + func42(s); +} + + +/* #expect: test.ll + +declare void @f38(ptr byval(%St256) align 32) +declare void @f37(ptr byval(<8 x float>) align 32) + +declare void @func40(ptr byval(%Two128) align 16) +define void @test.func41(ptr byval(%Two128) align 16 %0) + +declare void @func42(ptr byval(%Sa) align 16) +define void @test.func43(ptr byval(%Sa) align 16 %0) diff --git a/test/test_suite2/abi/darwinx64_1.c3t b/test/test_suite2/abi/darwinx64_1.c3t new file mode 100644 index 000000000..bbdf16a09 --- /dev/null +++ b/test/test_suite2/abi/darwinx64_1.c3t @@ -0,0 +1,48 @@ +// #target: macos-x64 +module test; + +fn char f0() { + return 0; +} + +fn short f1() { + return 0; +} + +fn int f2() { + return 0; +} + +fn float f3() { + return 0; +} + +fn double f4() { + return 0; +} + +fn void f6(char a0, short a1, int a2, long a3, void *a4) {} + +enum Enum7 : int { A, B, C } +fn void f7(Enum7 a0) {} + +struct Struct8 +{ + int a; + int b; +} + +fn Struct8 f8_1() { while (1) {} return Struct8 {}; } +fn void f8_2(Struct8 a0) {} + +/* #expect: test.ll + +define zeroext i8 @test.f0() +define signext i16 @test.f1() +define i32 @test.f2() +define float @test.f3() +define double @test.f4() +define void @test.f6(i8 zeroext %0, i16 signext %1, i32 %2, i64 %3, ptr %4) +define void @test.f7(i32 %0) +define i64 @test.f8_1() +define void @test.f8_2(i64 %0) #0 { diff --git a/test/test_suite2/abi/darwinx64_2.c3t b/test/test_suite2/abi/darwinx64_2.c3t new file mode 100644 index 000000000..800d90c26 --- /dev/null +++ b/test/test_suite2/abi/darwinx64_2.c3t @@ -0,0 +1,186 @@ +// #target: macos-x64 +module test; +import std; + +struct St12 +{ + int a @align(16); +} +fn St12 f12_0(void) { while (1) {}; unreachable(); } +fn void f12_1(St12 a0) {} + +struct St13_0 { long[3] f0; } +struct St13_1 { long[2] f0; } +fn St13_0 f13(int a, int b, int c, int d, + St13_1 e, int f) { while (1) {}; unreachable(); } + +fn void f14(int a, int b, int c, int d, int e, int f, ichar x) {} + +fn void f15(int a, int b, int c, int d, int e, int f, void *x) {} + +fn void f16(float a, float b, float c, float d, float e, float f, float g, float h, + float x) {} + +struct Fl18_s0 { int f0; } +fn void fl18(int a, Fl18_s0 f18_arg1) { while (1) {} } + +struct St20 @align(32) { + int x; + int y; +} +fn void f20(St20 x) {} + +struct StringRef +{ + int x; + char* ptr; +} +fn char *f21(StringRef s) { return s.x+s.ptr; } + +struct St22s @align(16) +{ ulong[2] x; } +fn void f22(St22s x, St22s y) { } + + + +struct St23S { + short f0; + uint f1; + int f2; +} + + +fn void f23(int a, St23S b) { +} + +struct St24s { int a; int b; } + +fn St23S f24(St23S *x, St24s *p2) +{ + return *x; + +} + +fn float[<4>] f25(float[<4>] x) { + return x+x; +} + +struct Foo26 { + int *x; + float *y; +} + +fn Foo26 f26(Foo26 *p) { + return *p; +} + + +struct V4f32wrapper { + float[<4>] v; +} + +fn V4f32wrapper f27(V4f32wrapper x) { + return x; +} + +// PR22563 - We should unwrap simple structs and arrays to pass +// and return them in the appropriate vector registers if possible. + +define V8f32 = float[<8>]; +struct V8f32wrapper { + V8f32 v; +} + +fn V8f32wrapper f27a(V8f32wrapper x) { + return x; +} + +struct V8f32wrapper_wrapper { + V8f32[1] v; +} + +fn V8f32wrapper_wrapper f27b(V8f32wrapper_wrapper x) { + return x; +} + +struct F28c { + double x; + int y; +} +fn void f28(F28c c) { +} + +struct Inner +{ + double x; + int y; +} +struct F29a +{ + Inner[1] c; +} + +fn void f29a(F29a a) { +} + +struct St0 { + char[8] f0; char f2; char f3; char f4; } +fn void f30(St0 p_4) { +} + +struct F31foo { float a, b, c; } +fn float f31(F31foo x) { + return x.c; +} + +define V1i64 = ulong[<1>]; + +fn V1i64 f34(V1i64 arg) { return arg; } + + +define V1i64_2 = uint[<2>]; +fn V1i64_2 f35(V1i64_2 arg) { return arg+arg; } + +define V2i32 = float[<2>]; +fn V2i32 f36(V2i32 arg) { return arg; } + + +/* #expect: test.ll + +define i32 @test.f12_0() +define void @test.f12_1(i32 %0) +define void @test.f13(ptr noalias sret(%St13_0) align 8 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr byval(%St13_1) align 8 %5, i32 %6) #0 { +define void @test.f14(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 signext %6) #0 { +define void @test.f15(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, ptr %6) + +define void @test.f16(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, float %8) + +define void @test.fl18(i32 %0, i32 %1) +define void @test.f20(ptr byval(%St20) align 32 %0) +define ptr @test.f21(i64 %0, ptr %1) + +define void @test.f22(i64 %0, i64 %1, i64 %2, i64 %3) +entry: + %x = alloca %St22s, align 16 + %y = alloca %St22s, align 16 + +define void @test.f23(i32 %0, i64 %1, i32 %2) +define { i64, i32 } @test.f24(ptr %0, ptr %1) + +define <4 x float> @test.f25(<4 x float> %0) #0 { +entry: + %fadd = fadd <4 x float> %0, %0 + ret <4 x float> %fadd +} + +define { ptr, ptr } @test.f26(ptr %0) +define <4 x float> @test.f27(<4 x float> %0) +define <8 x float> @test.f27a(<8 x float> %0) +define <8 x float> @test.f27b(<8 x float> %0) +define void @test.f28(double %0, i32 %1) +define void @test.f29a(double %0, i32 %1) +define void @test.f30(i64 %0, i24 %1) +define float @test.f31(<2 x float> %0, float %1) +define double @test.f34(double %0) +define double @test.f35(double %0) +define double @test.f36(double %0) \ No newline at end of file diff --git a/test/test_suite2/abi/literal_load.c3t b/test/test_suite2/abi/literal_load.c3t new file mode 100644 index 000000000..14abeb86f --- /dev/null +++ b/test/test_suite2/abi/literal_load.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 + +struct Test +{ + int x; +} + +Test foo = {}; + +extern fn void blorg(Test t); + +fn Test creator() +{ + blorg(Test{}); + return Test{}; +} + +/* #expect: literal_load.ll + +define i32 @literal_load.creator() #0 { +entry: + %literal = alloca %Test, align 4 + %literal1 = alloca %Test, align 4 + store i32 0, ptr %literal, align 4 + %0 = getelementptr inbounds %Test, ptr %literal, i32 0, i32 0 + %1 = load i32, ptr %0, align 4 + call void @blorg(i32 %1) + store i32 0, ptr %literal1, align 4 + %2 = getelementptr inbounds %Test, ptr %literal1, i32 0, i32 0 + %3 = load i32, ptr %2, align 4 + ret i32 %3 +} diff --git a/test/test_suite2/abi/literal_load_aarch64.c3t b/test/test_suite2/abi/literal_load_aarch64.c3t new file mode 100644 index 000000000..f9e98f8bb --- /dev/null +++ b/test/test_suite2/abi/literal_load_aarch64.c3t @@ -0,0 +1,36 @@ +// #target: linux-aarch64 +module literal_load; + +struct Test +{ + int x; +} + +Test foo = {}; + +extern fn void blorg(Test t); + +fn Test creator() +{ + blorg(Test{}); + return Test{}; +} + +/* #expect: literal_load.ll + +declare void @blorg(i64) #0 + +define i32 @literal_load.creator() #0 { +entry: + %literal = alloca %Test, align 4 + %literal1 = alloca %Test, align 4 + store i32 0, ptr %literal, align 4 + %0 = getelementptr inbounds %Test, ptr %literal, i32 0, i32 0 + %1 = load i32, ptr %0, align 4 + %2 = zext i32 %1 to i64 + call void @blorg(i64 %2) + store i32 0, ptr %literal1, align 4 + %3 = getelementptr inbounds %Test, ptr %literal1, i32 0, i32 0 + %4 = load i32, ptr %3, align 4 + ret i32 %4 +} \ No newline at end of file diff --git a/test/test_suite2/abi/literal_load_mingw.c3t b/test/test_suite2/abi/literal_load_mingw.c3t new file mode 100644 index 000000000..5b9e9eccd --- /dev/null +++ b/test/test_suite2/abi/literal_load_mingw.c3t @@ -0,0 +1,33 @@ +// #target: mingw-x64 +module literal_load; + +struct Test +{ + int x; +} + +Test foo = {}; + +extern fn void blorg(Test t); + +fn Test creator() +{ + blorg(Test{}); + return Test{}; +} + +/* #expect: literal_load.ll + +define i32 @literal_load.creator() #0 { +entry: + %literal = alloca %Test, align 4 + %literal1 = alloca %Test, align 4 + store i32 0, ptr %literal, align 4 + %0 = getelementptr inbounds %Test, ptr %literal, i32 0, i32 0 + %1 = load i32, ptr %0, align 4 + call void @blorg(i32 %1) + store i32 0, ptr %literal1, align 4 + %2 = getelementptr inbounds %Test, ptr %literal1, i32 0, i32 0 + %3 = load i32, ptr %2, align 4 + ret i32 %3 +} diff --git a/test/test_suite2/abi/macho_section_attributes.c3 b/test/test_suite2/abi/macho_section_attributes.c3 new file mode 100644 index 000000000..a889be39e --- /dev/null +++ b/test/test_suite2/abi/macho_section_attributes.c3 @@ -0,0 +1,8 @@ +// #target: macos-x64 + +int foo @section("foo, 12345678901234567 "); // #error: Mach-o requires the section to be at the most 16 characters +int bar @section("foo, "); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly? +int baz @section("foo"); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly? +int abc @section("foo,b,c,d,e,f"); // #error: Too many parts to the Mach-o section description. +int def @section("foo,b,c,d"); + diff --git a/test/test_suite2/abi/pass_large_aarch.c3t b/test/test_suite2/abi/pass_large_aarch.c3t new file mode 100644 index 000000000..52e15789a --- /dev/null +++ b/test/test_suite2/abi/pass_large_aarch.c3t @@ -0,0 +1,32 @@ +// #target: linux-aarch64 + +module pass_large; + + +struct Large +{ + void*[8] pointers; +} + +extern fn void pass_large(Large large); + +fn void example() +{ + Large l = {}; + pass_large(l); + pass_large(l); +} + +/* #expect: pass_large.ll + +define void @pass_large.example() +entry: + %l = alloca %Large, align 8 + %indirectarg = alloca %Large, align 8 + %indirectarg1 = alloca %Large, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %l, i8 0, i64 64, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %l, i32 64, i1 false) + call void @pass_large(ptr align 8 %indirectarg) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg1, ptr align 8 %l, i32 64, i1 false) + call void @pass_large(ptr align 8 %indirectarg1) + ret void diff --git a/test/test_suite2/abi/regcall_expand.c3t b/test/test_suite2/abi/regcall_expand.c3t new file mode 100644 index 000000000..6946518ce --- /dev/null +++ b/test/test_suite2/abi/regcall_expand.c3t @@ -0,0 +1,57 @@ +// #target: mingw-x64 +module test; + +extern fn void printf(char*, ...); + +struct Foo +{ + float[2] x; +} +fn void test(Foo x) @regcall +{ +} + +fn int main() +{ + test(Foo { }); + return 0; +} + +/* #expect: test.ll + +%Foo = type { [2 x float] } + +$.typeid.test.Foo = comdat any + +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, comdat, align 8 + +declare void @printf(ptr, ...) #0 + +define x86_regcallcc void @test.test(float %0, float %1) #0 { +entry: + %x = alloca %Foo, align 4 + %2 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %3 = getelementptr inbounds [2 x float], ptr %2, i64 0, i64 0 + store float %0, ptr %3, align 4 + %4 = getelementptr inbounds [2 x float], ptr %2, i64 0, i64 1 + store float %1, ptr %4, align 4 + ret void +} + +; Function Attrs: nounwind +define i32 @main() #0 { +entry: + %literal = alloca %Foo, align 4 + %0 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0 + %1 = getelementptr inbounds [2 x float], ptr %0, i64 0, i64 0 + store float 0.000000e+00, ptr %1, align 4 + %2 = getelementptr inbounds [2 x float], ptr %0, i64 0, i64 1 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0 + %4 = getelementptr inbounds [2 x float], ptr %3, i64 0, i64 0 + %loadexpanded = load float, ptr %4, align 4 + %5 = getelementptr inbounds [2 x float], ptr %3, i64 0, i64 1 + %loadexpanded1 = load float, ptr %5, align 4 + call x86_regcallcc void @test.test(float %loadexpanded, float %loadexpanded1) + ret i32 0 +} diff --git a/test/test_suite2/abi/riscv64-lp64-abi.c3t b/test/test_suite2/abi/riscv64-lp64-abi.c3t new file mode 100644 index 000000000..bb2819297 --- /dev/null +++ b/test/test_suite2/abi/riscv64-lp64-abi.c3t @@ -0,0 +1,51 @@ +// #target: linux-riscv64 +module test; + +struct Large { + long a, b, c, d; +} + +define V32i8 = char[<32>]; + +fn int f_scalar_stack_1(int a, int128 b, float c, float128 d, V32i8 e, + char f, char g, char h) { + return g + h; +} + +fn Large f_scalar_stack_2(double a, int128 b, float128 c, V32i8 d, + char e, ichar f, char g) { + return Large {(long)(a), e, f, g}; +} + +/* #expect: test.ll + +define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, float %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %e = alloca <32 x i8>, align 32 + call void @llvm.memcpy.p0.p0.i32(ptr align 32 %e, ptr align 32 %4, i32 32, i1 false) + %uisiext = zext i8 %6 to i32 + %uisiext1 = zext i8 %7 to i32 + %add = add i32 %uisiext, %uisiext1 + ret i32 %add +} + +define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 8 %0, double %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %d = alloca <32 x i8>, align 32 + %literal = alloca %Large, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 32 %d, ptr align 32 %4, i32 32, i1 false) + %8 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 0 + %fpsi = fptosi double %1 to i64 + store i64 %fpsi, ptr %8, align 8 + %9 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 1 + %uisiext = zext i8 %5 to i64 + store i64 %uisiext, ptr %9, align 8 + %10 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 2 + %sisiext = sext i8 %6 to i64 + store i64 %sisiext, ptr %10, align 8 + %11 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 3 + %uisiext1 = zext i8 %7 to i64 + store i64 %uisiext1, ptr %11, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 32, i1 false) + ret void +} diff --git a/test/test_suite2/abi/small_struct_x64.c3t b/test/test_suite2/abi/small_struct_x64.c3t new file mode 100644 index 000000000..1ca3fa243 --- /dev/null +++ b/test/test_suite2/abi/small_struct_x64.c3t @@ -0,0 +1,66 @@ +// #target: macos-x64 +module test; +struct Foo +{ + char a; + char b; + char c; +} + +fn int testing() +{ + Foo y = getFoo(Foo { 4, 5, 6 }); + return y.a + y.c; +} + +fn Foo getFoo(Foo f) +{ + return Foo { 1, 2, 3 }; +} + +/* #expect: test.ll + +define i32 @test.testing() #0 { +entry: + %y = alloca %Foo, align 1 + %literal = alloca %Foo, align 1 + %tempcoerce = alloca i24, align 4 + %result = alloca %Foo, align 1 + %0 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0 + store i8 4, ptr %0, align 1 + %1 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 1 + store i8 5, ptr %1, align 1 + %2 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 2 + store i8 6, ptr %2, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %tempcoerce, ptr align 1 %literal, i32 3, i1 false) + %3 = load i24, ptr %tempcoerce, align 4 + %4 = call i24 @test.getFoo(i24 %3) + store i24 %4, ptr %result, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 %result, i32 3, i1 false) + %5 = getelementptr inbounds %Foo, ptr %y, i32 0, i32 0 + %6 = load i8, ptr %5, align 1 + %uisiext = zext i8 %6 to i32 + %7 = getelementptr inbounds %Foo, ptr %y, i32 0, i32 2 + %8 = load i8, ptr %7, align 1 + %uisiext1 = zext i8 %8 to i32 + %add = add i32 %uisiext, %uisiext1 + ret i32 %add +} + +; Function Attrs: nounwind +define i24 @test.getFoo(i24 %0) #0 { +entry: + %f = alloca %Foo, align 1 + %literal = alloca %Foo, align 1 + %tempcoerce = alloca i24, align 4 + store i24 %0, ptr %f, align 1 + %1 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0 + store i8 1, ptr %1, align 1 + %2 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 1 + store i8 2, ptr %2, align 1 + %3 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 2 + store i8 3, ptr %3, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %tempcoerce, ptr align 1 %literal, i32 3, i1 false) + %4 = load i24, ptr %tempcoerce, align 4 + ret i24 %4 +} diff --git a/test/test_suite2/abi/sysv_direct_coerce.c3t b/test/test_suite2/abi/sysv_direct_coerce.c3t new file mode 100644 index 000000000..210a6218b --- /dev/null +++ b/test/test_suite2/abi/sysv_direct_coerce.c3t @@ -0,0 +1,43 @@ +// #target: macos-x64 +module foo; + +struct Rectangle +{ + float x; // Rectangle top-left corner position x + float y; // Rectangle top-left corner position y + float width; // Rectangle width + float height; // Rectangle height +} + +fn void test(Rectangle r) +{ + test(Rectangle { 1, 2, 3, 4 }); +} + +/* #expect: foo.ll + +define void @foo.test(<2 x float> %0, <2 x float> %1) #0 { +entry: + %r = alloca %Rectangle, align 4 + %literal = alloca %Rectangle, align 4 + %coerce = alloca %Rectangle, align 8 + %2 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %r, i32 0, i32 0 + store <2 x float> %0, ptr %2, align 4 + %3 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %r, i32 0, i32 1 + store <2 x float> %1, ptr %3, align 4 + %4 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 0 + store float 1.000000e+00, ptr %4, align 4 + %5 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 1 + store float 2.000000e+00, ptr %5, align 4 + %6 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 2 + store float 3.000000e+00, ptr %6, align 4 + %7 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 3 + store float 4.000000e+00, ptr %7, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %coerce, ptr align 4 %literal, i32 16, i1 false) + %8 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %coerce, i32 0, i32 0 + %lo = load <2 x float>, ptr %8, align 8 + %9 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %coerce, i32 0, i32 1 + %hi = load <2 x float>, ptr %9, align 8 + call void @foo.test(<2 x float> %lo, <2 x float> %hi) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/abi/test_sret.c3t b/test/test_suite2/abi/test_sret.c3t new file mode 100644 index 000000000..b2cf432f6 --- /dev/null +++ b/test/test_suite2/abi/test_sret.c3t @@ -0,0 +1,38 @@ +// #target: macos-x64 + +struct Abc { + long a; + long b; + long c; + long d; + long e; +} + +extern fn Abc foo1(); +extern fn Abc foo2(); + +fn void bar() { + Abc dummy1 = foo1(); + Abc dummy2 = foo2(); +} + +// Cleanup for this result, since it's creating an unnecessary sret. + +/* #expect: test_sret.ll + +declare void @foo1(ptr noalias sret(%Abc) align 8) #0 + +declare void @foo2(ptr noalias sret(%Abc) align 8) #0 + +define void @test_sret.bar() #0 { +entry: + %dummy1 = alloca %Abc, align 8 + %sretparam = alloca %Abc, align 8 + %dummy2 = alloca %Abc, align 8 + %sretparam1 = alloca %Abc, align 8 + call void @foo1(ptr sret(%Abc) align 8 %sretparam) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %dummy1, ptr align 8 %sretparam, i32 40, i1 false) + call void @foo2(ptr sret(%Abc) align 8 %sretparam1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %dummy2, ptr align 8 %sretparam1, i32 40, i1 false) + ret void +} diff --git a/test/test_suite2/abi/union_x64.c3t b/test/test_suite2/abi/union_x64.c3t new file mode 100644 index 000000000..fb8c9e4d6 --- /dev/null +++ b/test/test_suite2/abi/union_x64.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 + +module unionx64; + +union Foo +{ + long a; + char[12] b; +} +extern fn void hello2(Foo f); + +fn void hello(Foo f) +{ + hello2(f); +} + +/* #expect: unionx64.ll + +%Foo = type { i64, [8 x i8] } + +declare void @hello2(i64, i64) #0 + +define void @unionx64.hello(i64 %0, i64 %1) #0 { +entry: + %f = alloca %Foo, align 8 + %2 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 0 + store i64 %0, ptr %2, align 8 + %3 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + %4 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 0 + %lo = load i64, ptr %4, align 8 + %5 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 1 + %hi = load i64, ptr %5, align 8 + call void @hello2(i64 %lo, i64 %hi) + ret void +} + diff --git a/test/test_suite2/abi/vec2_aarch64.c3t b/test/test_suite2/abi/vec2_aarch64.c3t new file mode 100644 index 000000000..df230db68 --- /dev/null +++ b/test/test_suite2/abi/vec2_aarch64.c3t @@ -0,0 +1,95 @@ +// #target: linux-aarch64 +module abi; + +struct Vector2 { + float x; + float y; +} +extern fn Vector2 vector2_zero() { return Vector2 {}; } +extern fn Vector2 vector2_one() { return Vector2 {}; } +extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; } +extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; } +extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; } +extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; } + +/* #expect: abi.ll + +%Vector2 = type { float, float } + +define %Vector2 @vector2_zero() #0 { +entry: + %literal = alloca %Vector2, align 4 + %0 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %0, align 4 + %1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %1, align 4 + %2 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %2 +} + +define %Vector2 @vector2_one() #0 { +entry: + %literal = alloca %Vector2, align 4 + %0 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %0, align 4 + %1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %1, align 4 + %2 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %2 +} + +define %Vector2 @vector2_add([2 x float] %0, [2 x float] %1) #0 { +entry: + %v1 = alloca %Vector2, align 4 + %v2 = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + store [2 x float] %0, ptr %v1, align 4 + store [2 x float] %1, ptr %v2, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + %4 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %4 +} + +define %Vector2 @vector2_add_value([2 x float] %0, float %1) #0 { +entry: + %v = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + store [2 x float] %0, ptr %v, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + %4 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %4 +} + +define %Vector2 @vector2_subtract([2 x float] %0, [2 x float] %1) #0 { +entry: + %v1 = alloca %Vector2, align 4 + %v2 = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + store [2 x float] %0, ptr %v1, align 4 + store [2 x float] %1, ptr %v2, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + %4 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %4 +} + +define %Vector2 @vector2_subtract_value([2 x float] %0, float %1) #0 { +entry: + %v = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + store [2 x float] %0, ptr %v, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + %4 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %4 +} diff --git a/test/test_suite2/abi/vec2_wasm.c3t b/test/test_suite2/abi/vec2_wasm.c3t new file mode 100644 index 000000000..d2725970a --- /dev/null +++ b/test/test_suite2/abi/vec2_wasm.c3t @@ -0,0 +1,98 @@ +// #target: wasm32 +module abi; + +struct Vector2 { + float x; + float y; +} +extern fn Vector2 vector2_zero() { return Vector2 {}; } +extern fn Vector2 vector2_one() { return Vector2 {}; } +extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; } +extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; } +extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; } +extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; } + +/* #expect: abi.ll + +target triple = "wasm32-unknown-unknown" + +%Vector2 = type { float, float } + +define void @vector2_zero(ptr noalias sret(%Vector2) align 4 %0) #0 { +entry: + %literal = alloca %Vector2, align 4 + %1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %1, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +define void @vector2_one(ptr noalias sret(%Vector2) align 4 %0) #0 { +entry: + %literal = alloca %Vector2, align 4 + %1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %1, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +define void @vector2_add(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, ptr byval(%Vector2) align 4 %2) #0 { +entry: + %v1 = alloca %Vector2, align 4 + %v2 = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v1, ptr align 4 %1, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v2, ptr align 4 %2, i32 8, i1 false) + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %3, align 4 + %4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %4, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +define void @vector2_add_value(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, float %2) #0 { +entry: + %v = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v, ptr align 4 %1, i32 8, i1 false) + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %3, align 4 + %4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %4, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +define void @vector2_subtract(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, ptr byval(%Vector2) align 4 %2) #0 { +entry: + %v1 = alloca %Vector2, align 4 + %v2 = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v1, ptr align 4 %1, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v2, ptr align 4 %2, i32 8, i1 false) + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %3, align 4 + %4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %4, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +define void @vector2_subtract_value(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, float %2) #0 { +entry: + %v = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v, ptr align 4 %1, i32 8, i1 false) + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %3, align 4 + %4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %4, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + diff --git a/test/test_suite2/abi/vec2_x64.c3t b/test/test_suite2/abi/vec2_x64.c3t new file mode 100644 index 000000000..e0d60e110 --- /dev/null +++ b/test/test_suite2/abi/vec2_x64.c3t @@ -0,0 +1,107 @@ +// #target: macos-x64 +module abi; + +struct Vector2 { + float x; + float y; +} +extern fn Vector2 vector2_zero() { return Vector2 {}; } +extern fn Vector2 vector2_one() { return Vector2 {}; } +extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; } +extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; } +extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; } +extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; } + +/* #expect: abi.ll + +%Vector2 = type { float, float } + +define <2 x float> @vector2_zero() #0 { +entry: + %literal = alloca %Vector2, align 4 + %tempcoerce = alloca <2 x float>, align 8 + %0 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %0, align 4 + %1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %1, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 8, i1 false) + %2 = load <2 x float>, ptr %tempcoerce, align 8 + ret <2 x float> %2 +} + +define <2 x float> @vector2_one() #0 { +entry: + %literal = alloca %Vector2, align 4 + %tempcoerce = alloca <2 x float>, align 8 + %0 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %0, align 4 + %1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %1, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 8, i1 false) + %2 = load <2 x float>, ptr %tempcoerce, align 8 + ret <2 x float> %2 +} + +define <2 x float> @vector2_add(<2 x float> %0, <2 x float> %1) #0 { +entry: + %v1 = alloca %Vector2, align 4 + %v2 = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + %tempcoerce = alloca <2 x float>, align 8 + store <2 x float> %0, ptr %v1, align 4 + store <2 x float> %1, ptr %v2, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 8, i1 false) + %4 = load <2 x float>, ptr %tempcoerce, align 8 + ret <2 x float> %4 +} + +define <2 x float> @vector2_add_value(<2 x float> %0, float %1) #0 { +entry: + %v = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + %tempcoerce = alloca <2 x float>, align 8 + store <2 x float> %0, ptr %v, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 8, i1 false) + %4 = load <2 x float>, ptr %tempcoerce, align 8 + ret <2 x float> %4 +} + +define <2 x float> @vector2_subtract(<2 x float> %0, <2 x float> %1) #0 { +entry: + %v1 = alloca %Vector2, align 4 + %v2 = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + %tempcoerce = alloca <2 x float>, align 8 + store <2 x float> %0, ptr %v1, align 4 + store <2 x float> %1, ptr %v2, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 8, i1 false) + %4 = load <2 x float>, ptr %tempcoerce, align 8 + ret <2 x float> %4 +} + +define <2 x float> @vector2_subtract_value(<2 x float> %0, float %1) #0 { +entry: + %v = alloca %Vector2, align 4 + %literal = alloca %Vector2, align 4 + %tempcoerce = alloca <2 x float>, align 8 + store <2 x float> %0, ptr %v, align 4 + %2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1 + store float 0.000000e+00, ptr %3, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 8, i1 false) + %4 = load <2 x float>, ptr %tempcoerce, align 8 + ret <2 x float> %4 +} diff --git a/test/test_suite2/abi/x64alignarray.c3t b/test/test_suite2/abi/x64alignarray.c3t new file mode 100644 index 000000000..892d45fe0 --- /dev/null +++ b/test/test_suite2/abi/x64alignarray.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +module test; + +extern fn void test1_f(void *); + +fn void test1_g() +{ + float[4] x; + test1_f(&x); +} + +/* #expect: test.ll + +define void @test.test1_g() #0 { +entry: + %x = alloca [4 x float], align 16 + %0 = getelementptr inbounds [4 x float], ptr %x, i64 0, i64 0 + store float 0.000000e+00, ptr %0, align 4 + %1 = getelementptr inbounds [4 x float], ptr %x, i64 0, i64 1 + store float 0.000000e+00, ptr %1, align 4 + %2 = getelementptr inbounds [4 x float], ptr %x, i64 0, i64 2 + store float 0.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds [4 x float], ptr %x, i64 0, i64 3 + store float 0.000000e+00, ptr %3, align 4 + call void @test1_f(ptr %x) + ret void +} diff --git a/test/test_suite2/arrays/array_casts.c3t b/test/test_suite2/arrays/array_casts.c3t new file mode 100644 index 000000000..04c31c96b --- /dev/null +++ b/test/test_suite2/arrays/array_casts.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 + +module array_casts; + +fn void test() +{ + int[3] x; + int *y = &x; + int[] z = &x; +} + +/* #expect: array_casts.ll + +%"int[]" = type { ptr, i64 } + +define void @array_casts.test() #0 { +entry: + %x = alloca [3 x i32], align 4 + %y = alloca ptr, align 8 + %z = alloca %"int[]", align 8 + %0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 0 + store i32 0, ptr %0, align 4 + %1 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + store i32 0, ptr %1, align 4 + %2 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 2 + store i32 0, ptr %2, align 4 + store ptr %x, ptr %y, align 8 + %3 = insertvalue %"int[]" undef, ptr %x, 0 + %4 = insertvalue %"int[]" %3, i64 3, 1 + store %"int[]" %4, ptr %z, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/arrays/array_invalid_casts.c3 b/test/test_suite2/arrays/array_invalid_casts.c3 new file mode 100644 index 000000000..a197e4fd3 --- /dev/null +++ b/test/test_suite2/arrays/array_invalid_casts.c3 @@ -0,0 +1,12 @@ + +fn void test() +{ + int[3] x; + double *y = &x; // #error: 'int[3]*' to 'double* +} + +fn void test2() +{ + int[3] x; + double[] z = &x; // #error: 'int[3]*' into 'double[]' +} \ No newline at end of file diff --git a/test/test_suite2/arrays/array_literal.c3t b/test/test_suite2/arrays/array_literal.c3t new file mode 100644 index 000000000..dd96c65e0 --- /dev/null +++ b/test/test_suite2/arrays/array_literal.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +module array_literal; + +fn double test(uint x) +{ + double[30] student_t = { 0.0 , 12.706 , 4.303 , 3.182 , 2.776 , 2.571 , + 2.447 , 2.365 , 2.306 , 2.262 , 2.228 , + 2.201 , 2.179 , 2.160 , 2.145 , 2.131 , + 2.120 , 2.110 , 2.101 , 2.093 , 2.086 , + 2.080 , 2.074 , 2.069 , 2.064 , 2.060 , + 2.056 , 2.052 , 2.048 , 2.045 }; + return student_t[x]; +} + +/* #expect: array_literal.ll + +@.__const = private unnamed_addr constant [30 x double] [double 0.000000e+00, double 1.270600e+01, double 4.303000e+00, double 3.182000e+00, double 2.776000e+00, double 2.571000e+00, double 2.447000e+00, double 2.365000e+00, double 2.306000e+00, double 2.262000e+00, double 2.228000e+00, double 2.201000e+00, double 2.179000e+00, double 2.160000e+00, double 2.145000e+00, double 2.131000e+00, double 2.120000e+00, double 2.110000e+00, double 2.101000e+00, double 2.093000e+00, double 2.086000e+00, double 2.080000e+00, double 2.074000e+00, double 2.069000e+00, double 2.064000e+00, double 2.060000e+00, double 2.056000e+00, double 2.052000e+00, double 2.048000e+00, double 2.045000e+00], align 16 + +define double @array_literal.test(i32 %0) #0 { +entry: + %student_t = alloca [30 x double], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %student_t, ptr align 16 @.__const, i32 240, i1 false) + %uiuiext = zext i32 %0 to i64 + %1 = getelementptr inbounds [30 x double], ptr %student_t, i64 0, i64 %uiuiext + %2 = load double, ptr %1, align 8 + ret double %2 +} diff --git a/test/test_suite2/arrays/array_struct.c3t b/test/test_suite2/arrays/array_struct.c3t new file mode 100644 index 000000000..2d4ebb1c0 --- /dev/null +++ b/test/test_suite2/arrays/array_struct.c3t @@ -0,0 +1,13 @@ +// #target: macos-x64 +module test; + +struct Foo +{ + int x, y; +} + +private Foo[10] array; + +// #expect: test.ll + +@test.array = protected unnamed_addr global [10 x %Foo] zeroinitializer, align 16 \ No newline at end of file diff --git a/test/test_suite2/arrays/complex_array_const.c3t b/test/test_suite2/arrays/complex_array_const.c3t new file mode 100644 index 000000000..27fdcd496 --- /dev/null +++ b/test/test_suite2/arrays/complex_array_const.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 +module test; + +struct Connection +{ + long to; + char* type; + long length; +} + +private Connection[3] link += { {1, "link1", 10}, + {2, "link2", 20}, + {3, "link3", 30} }; + +/* #expect: test.ll + +@.typeid.test.Connection = linkonce constant { i8, i64 } { i8 10, i64 3 }, align 8 +@.str = private unnamed_addr constant [6 x i8] c"link1\00", align 1 +@.str.1 = private unnamed_addr constant [6 x i8] c"link2\00", align 1 +@.str.2 = private unnamed_addr constant [6 x i8] c"link3\00", align 1 +@test.link = protected unnamed_addr global [3 x %Connection] [%Connection { i64 1, ptr @.str, i64 10 }, %Connection { i64 2, ptr @.str.1, i64 20 }, %Connection { i64 3, ptr @.str.2, i64 30 }], align 16 diff --git a/test/test_suite2/arrays/global_array_non_const.c3 b/test/test_suite2/arrays/global_array_non_const.c3 new file mode 100644 index 000000000..7f6512ea8 --- /dev/null +++ b/test/test_suite2/arrays/global_array_non_const.c3 @@ -0,0 +1,17 @@ + +const int CONSTANT = 1; +int[CONSTANT] a2; + +const bool B = true; +int[B] c2; // #error: Expected an integer size. + +int non_constant = 10; +int[non_constant] b; // #error: Expected a constant value as + +fn int foo() +{ + return 10; +} + +int[foo()] c; // #error: Expected a constant value as + diff --git a/test/test_suite2/arrays/index_from_back.c3t b/test/test_suite2/arrays/index_from_back.c3t new file mode 100644 index 000000000..4fdbb17be --- /dev/null +++ b/test/test_suite2/arrays/index_from_back.c3t @@ -0,0 +1,57 @@ +// #target: macos-x64 + +module test; + +fn void test(int[10] x, int[<10>] y) +{ + int a = x[4]; + int b = x[^2]; + int c = y[4]; + int d = y[^2]; + int j = 3; + int e = y[^j]; + int f = x[^j]; +} + +/* #expect: test.ll + +define void @test.test(ptr byval([10 x i32]) align 8 %0, ptr byval(<10 x i32>) align 64 %1) #0 { +entry: + %x = alloca [10 x i32], align 4 + %y = alloca <10 x i32>, align 64 + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %c = alloca i32, align 4 + %d = alloca i32, align 4 + %j = alloca i32, align 4 + %e = alloca i32, align 4 + %f = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 8 %0, i32 40, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 64 %y, ptr align 64 %1, i32 64, i1 false) + %2 = getelementptr inbounds [10 x i32], ptr %x, i64 0, i64 4 + %3 = load i32, ptr %2, align 4 + store i32 %3, ptr %a, align 4 + %4 = getelementptr inbounds [10 x i32], ptr %x, i64 0, i64 8 + %5 = load i32, ptr %4, align 4 + store i32 %5, ptr %b, align 4 + %6 = load <10 x i32>, ptr %y, align 64 + %7 = extractelement <10 x i32> %6, i64 4 + store i32 %7, ptr %c, align 4 + %8 = load <10 x i32>, ptr %y, align 64 + %9 = extractelement <10 x i32> %8, i64 8 + store i32 %9, ptr %d, align 4 + store i32 3, ptr %j, align 4 + %10 = load <10 x i32>, ptr %y, align 64 + %11 = load i32, ptr %j, align 4 + %sisiext = sext i32 %11 to i64 + %12 = sub nuw i64 10, %sisiext + %13 = extractelement <10 x i32> %10, i64 %12 + store i32 %13, ptr %e, align 4 + %14 = load i32, ptr %j, align 4 + %sisiext1 = sext i32 %14 to i64 + %15 = sub nuw i64 10, %sisiext1 + %16 = getelementptr inbounds [10 x i32], ptr %x, i64 0, i64 %15 + %17 = load i32, ptr %16, align 4 + store i32 %17, ptr %f, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/arrays/index_into_global.c3t b/test/test_suite2/arrays/index_into_global.c3t new file mode 100644 index 000000000..544e7c53e --- /dev/null +++ b/test/test_suite2/arrays/index_into_global.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 + +module foo; + +struct Bar { + int a; +} + +Bar[6] bar; + +fn int main() +{ + test_bar(0); + return 0; +} + +fn void test_bar(int idx) +{ + bar[idx].a = 0; + bar[0].a = idx; +} + +/* #expect: foo.ll + +define void @foo.test_bar(i32 %0) #0 { +entry: + %sisiext = sext i32 %0 to i64 + %1 = getelementptr inbounds [6 x %Bar], ptr @foo.bar, i64 0, i64 %sisiext + %2 = getelementptr inbounds %Bar, ptr %1, i32 0, i32 0 + store i32 0, ptr %2, align 4 + store i32 %0, ptr @foo.bar, align 4 + ret void +} diff --git a/test/test_suite2/arrays/inferred_array_err.c3 b/test/test_suite2/arrays/inferred_array_err.c3 new file mode 100644 index 000000000..0e7dabd0b --- /dev/null +++ b/test/test_suite2/arrays/inferred_array_err.c3 @@ -0,0 +1,7 @@ +fn int[*] hello() // #error: Inferred array types can only be used in declarations with initializers +{ + return int[3] { 1, 2, 3}; +} + +int[*] c; // #error: Inferred array types can only be used in declarations with initializers + diff --git a/test/test_suite2/arrays/inferred_array_err2.c3 b/test/test_suite2/arrays/inferred_array_err2.c3 new file mode 100644 index 000000000..b3c4ebf9e --- /dev/null +++ b/test/test_suite2/arrays/inferred_array_err2.c3 @@ -0,0 +1,5 @@ +fn void test() +{ + int[3] z; + (int[*])(z); // #error: Inferred array types can only be used in declarations with initializers +} \ No newline at end of file diff --git a/test/test_suite2/arrays/negative_array.c3 b/test/test_suite2/arrays/negative_array.c3 new file mode 100644 index 000000000..44d656f15 --- /dev/null +++ b/test/test_suite2/arrays/negative_array.c3 @@ -0,0 +1,5 @@ + +int[-1] a; // #error: An array may not have a negative size +int[10-20] b; // #error: An array may not have a negative size +int[<-1>] c; // #error: A vector may not have a negative width +int[<10-20>] d; // #error: A vector may not have a negative width diff --git a/test/test_suite2/arrays/slice.c3 b/test/test_suite2/arrays/slice.c3 new file mode 100644 index 000000000..6d12e07c3 --- /dev/null +++ b/test/test_suite2/arrays/slice.c3 @@ -0,0 +1,7 @@ +fn void test() +{ + int[3] x = { 1, 2, 3 }; + int[] z = &x; + z[1]; +// z.size(); +} \ No newline at end of file diff --git a/test/test_suite2/assert/assert_variants.c3t b/test/test_suite2/assert/assert_variants.c3t new file mode 100644 index 000000000..fa9add3f5 --- /dev/null +++ b/test/test_suite2/assert/assert_variants.c3t @@ -0,0 +1,62 @@ +// #target: windows-x64 + +fn int foo() +{ + return 1; +} + +fn void test() +{ + int x = foo(); + int y = foo(); + int z = foo(); + assert(x > 0); + assert(y > 0 && z > 0); + assert(x > 0 && y > 0 && z > 0); + assert(foo() > 0); + assert(x > 0 && foo() > 0); + assert(!(x < 1 || y < 1), "Foo"); +} + + +// #expect: assert_variants.ll + + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %z = alloca i32, align 4 + %0 = call i32 @assert_variants.foo() + store i32 %0, ptr %x, align 4 + %1 = call i32 @assert_variants.foo() + store i32 %1, ptr %y, align 4 + %2 = call i32 @assert_variants.foo() + store i32 %2, ptr %z, align 4 + %3 = load i32, ptr %x, align 4 + %gt = icmp sgt i32 %3, 0 + call void @llvm.assume(i1 %gt) + %4 = load i32, ptr %y, align 4 + %gt1 = icmp sgt i32 %4, 0 + call void @llvm.assume(i1 %gt1) + %5 = load i32, ptr %z, align 4 + %gt2 = icmp sgt i32 %5, 0 + call void @llvm.assume(i1 %gt2) + %6 = load i32, ptr %x, align 4 + %gt3 = icmp sgt i32 %6, 0 + call void @llvm.assume(i1 %gt3) + %7 = load i32, ptr %y, align 4 + %gt4 = icmp sgt i32 %7, 0 + call void @llvm.assume(i1 %gt4) + %8 = load i32, ptr %z, align 4 + %gt5 = icmp sgt i32 %8, 0 + call void @llvm.assume(i1 %gt5) + %9 = load i32, ptr %x, align 4 + %gt6 = icmp sgt i32 %9, 0 + call void @llvm.assume(i1 %gt6) + %10 = load i32, ptr %x, align 4 + %lt = icmp slt i32 %10, 1 + %not = xor i1 %lt, true + call void @llvm.assume(i1 %not) + %11 = load i32, ptr %y, align 4 + %lt7 = icmp slt i32 %11, 1 + %not8 = xor i1 %lt7, true + call void @llvm.assume(i1 %not8) + ret void \ No newline at end of file diff --git a/test/test_suite2/assert/global_static_assert_not_constant.c3 b/test/test_suite2/assert/global_static_assert_not_constant.c3 new file mode 100644 index 000000000..9d1c3496d --- /dev/null +++ b/test/test_suite2/assert/global_static_assert_not_constant.c3 @@ -0,0 +1,3 @@ +int x = 3; + +$assert(x == 3); // #error: Compile time evaluation requires a compile time constant value. \ No newline at end of file diff --git a/test/test_suite2/assert/local_static_assert_not_constant.c3 b/test/test_suite2/assert/local_static_assert_not_constant.c3 new file mode 100644 index 000000000..cc02a64ca --- /dev/null +++ b/test/test_suite2/assert/local_static_assert_not_constant.c3 @@ -0,0 +1,20 @@ +int x = 3; + +fn void test() +{ + $assert(x == 3); // #error: Compile time evaluation requires a compile time constant value. +} + +fn void test2() +{ + int i = 0; + $assert(1); + $assert(i == 0); // #error: Compile time evaluation requires a compile time constant value. +} + +fn int foo(); +fn void test3() +{ + int i = 0; + $assert(foo() == 0); // #error: Compile time evaluation requires a compile time constant value. +} diff --git a/test/test_suite2/assert/static_assert.c3 b/test/test_suite2/assert/static_assert.c3 new file mode 100644 index 000000000..a49691433 --- /dev/null +++ b/test/test_suite2/assert/static_assert.c3 @@ -0,0 +1,8 @@ + +const int FOO = 2; + +fn void test() +{ + $assert(FOO == 2, "Bad"); + $assert(FOO == 0, "Good"); // #error: Compile time assert - Good +} \ No newline at end of file diff --git a/test/test_suite2/assert/unreachable.c3t b/test/test_suite2/assert/unreachable.c3t new file mode 100644 index 000000000..f6b6df77c --- /dev/null +++ b/test/test_suite2/assert/unreachable.c3t @@ -0,0 +1,40 @@ +fn int foo() +{ + return 1; +} + +fn void test() +{ + int x = foo(); + if (x > 0) return; + unreachable(); + x++; +} + + +/* #expect: unreachable.ll + + +define void @unreachable.test() #0 { +entry: + %x = alloca i32, align 4 + %0 = call i32 @unreachable.foo() + store i32 %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %gt = icmp sgt i32 %1, 0 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret void + +if.exit: ; preds = %entry + call void @"std::core::builtin.panic"(ptr @.str, ptr @.str.1, ptr @.str.2, i32 10) + unreachable + +after.unreachable: ; No predecessors! + %2 = load i32, ptr %x, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %x, align 4 + ret void +} + diff --git a/test/test_suite2/assignment/int_assign.c3t b/test/test_suite2/assignment/int_assign.c3t new file mode 100644 index 000000000..f6663027d --- /dev/null +++ b/test/test_suite2/assignment/int_assign.c3t @@ -0,0 +1,69 @@ +module test; + +fn int foo() +{ + int x = 0; + int y; + x += y; + x -= y; + x %= y; + x /= y; + x *= y; + x <<= y; + x >>= y; + x ^= y; + x |= y; + x &= y; + return x; +} + + +// #expect: test.ll + + %x = alloca i32, align 4 + %y = alloca i32, align 4 + store i32 0, ptr %x, align 4 + store i32 0, ptr %y, align 4 + %0 = load i32, ptr %x, align 4 + %1 = load i32, ptr %y, align 4 + %add = add i32 %0, %1 + store i32 %add, ptr %x, align 4 + %2 = load i32, ptr %x, align 4 + %3 = load i32, ptr %y, align 4 + %sub = sub i32 %2, %3 + store i32 %sub, ptr %x, align 4 + %4 = load i32, ptr %x, align 4 + %5 = load i32, ptr %y, align 4 + %smod = srem i32 %4, %5 + store i32 %smod, ptr %x, align 4 + %6 = load i32, ptr %x, align 4 + %7 = load i32, ptr %y, align 4 + %sdiv = sdiv i32 %6, %7 + store i32 %sdiv, ptr %x, align 4 + %8 = load i32, ptr %x, align 4 + %9 = load i32, ptr %y, align 4 + %mul = mul i32 %8, %9 + store i32 %mul, ptr %x, align 4 + %10 = load i32, ptr %x, align 4 + %11 = load i32, ptr %y, align 4 + %shl = shl i32 %10, %11 + %12 = freeze i32 %shl + store i32 %12, ptr %x, align 4 + %13 = load i32, ptr %x, align 4 + %14 = load i32, ptr %y, align 4 + %ashr = ashr i32 %13, %14 + %15 = freeze i32 %ashr + store i32 %15, ptr %x, align 4 + %16 = load i32, ptr %x, align 4 + %17 = load i32, ptr %y, align 4 + %xor = xor i32 %16, %17 + store i32 %xor, ptr %x, align 4 + %18 = load i32, ptr %x, align 4 + %19 = load i32, ptr %y, align 4 + %or = or i32 %18, %19 + store i32 %or, ptr %x, align 4 + %20 = load i32, ptr %x, align 4 + %21 = load i32, ptr %y, align 4 + %and = and i32 %20, %21 + store i32 %and, ptr %x, align 4 + %22 = load i32, ptr %x, align 4 diff --git a/test/test_suite2/attributes/recursive_attributes.c3 b/test/test_suite2/attributes/recursive_attributes.c3 new file mode 100644 index 000000000..f3e6a9a0b --- /dev/null +++ b/test/test_suite2/attributes/recursive_attributes.c3 @@ -0,0 +1,17 @@ +module test; + +define @Align(y) = @Align16(y / 2); +define @Align16(x) = @align(4), @Align(8 * x); // #error: Recursive declaration of attribute +define @Test = @noinline; +struct Foo +{ + int z; + int xy @Align16(8); +} + +Foo f; + +fn void testme() @Test +{ + int x; +} diff --git a/test/test_suite2/attributes/user_defined_attributes.c3t b/test/test_suite2/attributes/user_defined_attributes.c3t new file mode 100644 index 000000000..c598162f0 --- /dev/null +++ b/test/test_suite2/attributes/user_defined_attributes.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 + +module test; + +define @Align(y) = @align(y); +define @Align16(x) = @Align(8 * x), @align(1024); +define @Test = @noinline; +define @TestZero; +struct Foo +{ + int z; + int xy @Align16(8); +} + +Foo f; + +fn void testme() @Test +{ + int x; +} + +fn void main() @TestZero +{ + testme(); +} + +/* #expect: test.ll + +%Foo = type { i32, [1020 x i8], i32, [1020 x i8] } + +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@test.f = local_unnamed_addr global %Foo zeroinitializer, align 1024 + +define void @test.testme() #0 { +entry: + %x = alloca i32, align 4 + store i32 0, ptr %x, align 4 + ret void +} + +define void @test.main() #1 { +entry: + call void @test.testme() + ret void +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/address_of_bitstruct.c3 b/test/test_suite2/bitstruct/address_of_bitstruct.c3 new file mode 100644 index 000000000..7fe1d41ba --- /dev/null +++ b/test/test_suite2/bitstruct/address_of_bitstruct.c3 @@ -0,0 +1,15 @@ +bitstruct BitField : char +{ + int a : 0..2; + int b : 4..5; + int c : 6..7; +} + +fn void test() +{ + BitField x; + BitField* z = &x; + x.a; + z.a; + &x.a; // #error: You cannot take the address of a bitstruct member +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/array_with_boolean.c3t b/test/test_suite2/bitstruct/array_with_boolean.c3t new file mode 100644 index 000000000..1d113eda7 --- /dev/null +++ b/test/test_suite2/bitstruct/array_with_boolean.c3t @@ -0,0 +1,71 @@ +// #target: macos-x64 + +module foo; + +bitstruct BitField : char[3] +{ + int a : 0..2; + int b : 3..8; + int c : 9..18; + bool d : 19; + bool e : 20; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + BitField xx = { 2, 3, 15, true, false }; + BitField xy = { 2, 3, 15, false, true }; + printf("%x, %x, %x, %d, %d\n", xx.a, xx.b, xx.c, xx.d, xx.e); +} + + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %xx = alloca [3 x i8], align 1 + %xy = alloca [3 x i8], align 1 + store [3 x i8] c"\1A\1E\08", ptr %xx, align 1 + store [3 x i8] c"\1A\1E\10", ptr %xy, align 1 + %0 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %1 = load i8, ptr %0, align 1 + %2 = zext i8 %1 to i32 + %3 = shl i32 %2, 29 + %4 = ashr i32 %3, 29 + %5 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %6 = load i8, ptr %5, align 1 + %7 = zext i8 %6 to i32 + %8 = lshr i32 %7, 3 + %9 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %10 = load i8, ptr %9, align 1 + %11 = zext i8 %10 to i32 + %12 = shl i32 %11, 5 + %13 = or i32 %12, %8 + %14 = shl i32 %13, 26 + %15 = ashr i32 %14, 26 + %16 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %17 = load i8, ptr %16, align 1 + %18 = zext i8 %17 to i32 + %19 = lshr i32 %18, 1 + %20 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %21 = load i8, ptr %20, align 1 + %22 = zext i8 %21 to i32 + %23 = shl i32 %22, 7 + %24 = or i32 %23, %19 + %25 = shl i32 %24, 22 + %26 = ashr i32 %25, 22 + %27 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %28 = load i8, ptr %27, align 1 + %29 = lshr i8 %28, 3 + %30 = trunc i8 %29 to i1 + %boolsi = zext i1 %30 to i32 + %31 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %32 = load i8, ptr %31, align 1 + %33 = lshr i8 %32, 4 + %34 = trunc i8 %33 to i1 + %boolsi1 = zext i1 %34 to i32 + call void (ptr, ...) @printf(ptr @.str, i32 %4, i32 %15, i32 %26, i32 %boolsi, i32 %boolsi1) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/bitfield_access.c3t b/test/test_suite2/bitstruct/bitfield_access.c3t new file mode 100644 index 000000000..3c752951b --- /dev/null +++ b/test/test_suite2/bitstruct/bitfield_access.c3t @@ -0,0 +1,180 @@ +// #target: macos-x64 + +module foo; + +bitstruct BitField : char +{ + int a : 0..2; + int b : 4..5; + int c : 6..7; +} + +bitstruct BitFieldI : ushort +{ + int a : 0..4; + int b : 5..10; + int c : 11..15; +} + + +struct Packet +{ + bitstruct : int + { + int a : 0..2; + int b : 3..5; + int c : 6..10; + } + int packet_id; +} + +bitstruct BitField3 : char[3] +{ + int a : 0..2; + int b : 3..8; + int c : 9..18; + int d : 19..23; +} + +bitstruct BitField3u : char[3] +{ + uint a : 0..2; + uint b : 3..8; + uint c : 9..18; + uint d : 19..23; +} + +bitstruct BitField4 : char[3] +{ + int a : 0..2; + int b : 3..7; + int c : 8..15; + int d : 16..19; +} + +bitstruct BitFieldCross : char[5] +{ + uint a : 5..22; +} + +BitField c = { 2, -1, 1 }; + +extern fn void printf(char*, ...); + +fn void main() +{ + BitField b = { 3, -1, 1 }; + BitFieldI c1 = { 5, 0, 0 }; + BitFieldI c2 = { 0, 3, 0 }; + BitFieldI c3 = { 0, 0, 9 }; + BitFieldI c4 = { -5, 7, 9 }; + BitFieldI c5 = { -5, 0, 0 }; + BitFieldI c6 = { 5, 0, 0 }; + BitFieldI c7 = { 0, 0, 5 }; + + BitField3 e1 = { 3, 1, 3, 4 }; + BitField3 e2 = { 1, 1, 3, 4 }; + BitField3 e3 = { 2, 1, 3, 4 }; + BitField d = { }; + + printf("%d\n", e1.a); + printf("%d\n", e2.a); + printf("%d\n", e3.a); + + BitField3u z1 = { 3, 1, 3, 4 }; + BitField3u z2 = { 4, 1, 3, 4 }; + BitField3u z3 = { 7, 1, 3, 4 }; + printf("%u\n", z1.a); + printf("%u\n", z2.a); + printf("%u\n", z3.a); + BitFieldCross xx = { 0x1238 }; + printf("%x\n", xx.a); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %b = alloca i8, align 1 + %c1 = alloca i16, align 2 + %c2 = alloca i16, align 2 + %c3 = alloca i16, align 2 + %c4 = alloca i16, align 2 + %c5 = alloca i16, align 2 + %c6 = alloca i16, align 2 + %c7 = alloca i16, align 2 + %e1 = alloca [3 x i8], align 1 + %e2 = alloca [3 x i8], align 1 + %e3 = alloca [3 x i8], align 1 + %d = alloca i8, align 1 + %z1 = alloca [3 x i8], align 1 + %z2 = alloca [3 x i8], align 1 + %z3 = alloca [3 x i8], align 1 + %xx = alloca [5 x i8], align 1 + store i8 115, ptr %b, align 1 + store i16 5, ptr %c1, align 2 + store i16 96, ptr %c2, align 2 + store i16 18432, ptr %c3, align 2 + store i16 18683, ptr %c4, align 2 + store i16 27, ptr %c5, align 2 + store i16 5, ptr %c6, align 2 + store i16 10240, ptr %c7, align 2 + store [3 x i8] c"\0B\06 ", ptr %e1, align 1 + store [3 x i8] c"\09\06 ", ptr %e2, align 1 + store [3 x i8] c"\0A\06 ", ptr %e3, align 1 + store i8 0, ptr %d, align 1 + %0 = getelementptr inbounds [3 x i8], ptr %e1, i64 0, i64 0 + %1 = load i8, ptr %0, align 1 + %2 = zext i8 %1 to i32 + %3 = shl i32 %2, 29 + %4 = ashr i32 %3, 29 + call void (ptr, ...) @printf(ptr @.str, i32 %4) + %5 = getelementptr inbounds [3 x i8], ptr %e2, i64 0, i64 0 + %6 = load i8, ptr %5, align 1 + %7 = zext i8 %6 to i32 + %8 = shl i32 %7, 29 + %9 = ashr i32 %8, 29 + call void (ptr, ...) @printf(ptr @.str.1, i32 %9) + %10 = getelementptr inbounds [3 x i8], ptr %e3, i64 0, i64 0 + %11 = load i8, ptr %10, align 1 + %12 = zext i8 %11 to i32 + %13 = shl i32 %12, 29 + %14 = ashr i32 %13, 29 + call void (ptr, ...) @printf(ptr @.str.2, i32 %14) + store [3 x i8] c"\0B\06 ", ptr %z1, align 1 + store [3 x i8] c"\0C\06 ", ptr %z2, align 1 + store [3 x i8] c"\0F\06 ", ptr %z3, align 1 + %15 = getelementptr inbounds [3 x i8], ptr %z1, i64 0, i64 0 + %16 = load i8, ptr %15, align 1 + %17 = zext i8 %16 to i32 + %18 = and i32 7, %17 + call void (ptr, ...) @printf(ptr @.str.3, i32 %18) + %19 = getelementptr inbounds [3 x i8], ptr %z2, i64 0, i64 0 + %20 = load i8, ptr %19, align 1 + %21 = zext i8 %20 to i32 + %22 = and i32 7, %21 + call void (ptr, ...) @printf(ptr @.str.4, i32 %22) + %23 = getelementptr inbounds [3 x i8], ptr %z3, i64 0, i64 0 + %24 = load i8, ptr %23, align 1 + %25 = zext i8 %24 to i32 + %26 = and i32 7, %25 + call void (ptr, ...) @printf(ptr @.str.5, i32 %26) + store [5 x i8] c"\00G\02\00\00", ptr %xx, align 1 + %27 = getelementptr inbounds [5 x i8], ptr %xx, i64 0, i64 0 + %28 = load i8, ptr %27, align 1 + %29 = zext i8 %28 to i32 + %30 = lshr i32 %29, 5 + %31 = getelementptr inbounds [5 x i8], ptr %xx, i64 0, i64 1 + %32 = load i8, ptr %31, align 1 + %33 = zext i8 %32 to i32 + %34 = shl i32 %33, 3 + %35 = or i32 %34, %30 + %36 = getelementptr inbounds [5 x i8], ptr %xx, i64 0, i64 2 + %37 = load i8, ptr %36, align 1 + %38 = zext i8 %37 to i32 + %39 = shl i32 %38, 11 + %40 = or i32 %39, %35 + %41 = and i32 262143, %40 + call void (ptr, ...) @printf(ptr @.str.6, i32 %41) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/bitstruct_access_signed.c3t b/test/test_suite2/bitstruct/bitstruct_access_signed.c3t new file mode 100644 index 000000000..9e7e5c25a --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_access_signed.c3t @@ -0,0 +1,91 @@ +// #target: macos-x64 + +module foo; + +bitstruct BitFieldCross : char[3] +{ + uint d : 0..4; + int a : 5..22; + uint c : 23..23; +} + +bitstruct BitFieldCrossU : char[3] +{ + uint d : 0..4; + uint a : 5..22; + uint c : 23..23; +} +extern fn void printf(char*, ...); + +fn void main() +{ + BitFieldCross xx = { 0, -17, 0 }; + printf("%d\n", xx.a); + xx = { 0x1f, -17, 1 }; + printf("%d\n", xx.a); + BitFieldCrossU xxu = { 0x1f, 0x15678, 1 }; + printf("%x\n", xxu.a); + +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %xx = alloca [3 x i8], align 1 + %xxu = alloca [3 x i8], align 1 + store [3 x i8] c"\E0\FD\7F", ptr %xx, align 1 + %0 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %1 = load i8, ptr %0, align 1 + %2 = zext i8 %1 to i32 + %3 = lshr i32 %2, 5 + %4 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %5 = load i8, ptr %4, align 1 + %6 = zext i8 %5 to i32 + %7 = shl i32 %6, 3 + %8 = or i32 %7, %3 + %9 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %10 = load i8, ptr %9, align 1 + %11 = zext i8 %10 to i32 + %12 = shl i32 %11, 11 + %13 = or i32 %12, %8 + %14 = shl i32 %13, 14 + %15 = ashr i32 %14, 14 + call void (ptr, ...) @printf(ptr @.str, i32 %15) + store [3 x i8] c"\FF\FD\FF", ptr %xx, align 1 + %16 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %17 = load i8, ptr %16, align 1 + %18 = zext i8 %17 to i32 + %19 = lshr i32 %18, 5 + %20 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %21 = load i8, ptr %20, align 1 + %22 = zext i8 %21 to i32 + %23 = shl i32 %22, 3 + %24 = or i32 %23, %19 + %25 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %26 = load i8, ptr %25, align 1 + %27 = zext i8 %26 to i32 + %28 = shl i32 %27, 11 + %29 = or i32 %28, %24 + %30 = shl i32 %29, 14 + %31 = ashr i32 %30, 14 + call void (ptr, ...) @printf(ptr @.str.1, i32 %31) + store [3 x i8] c"\1F\CF\AA", ptr %xxu, align 1 + %32 = getelementptr inbounds [3 x i8], ptr %xxu, i64 0, i64 0 + %33 = load i8, ptr %32, align 1 + %34 = zext i8 %33 to i32 + %35 = lshr i32 %34, 5 + %36 = getelementptr inbounds [3 x i8], ptr %xxu, i64 0, i64 1 + %37 = load i8, ptr %36, align 1 + %38 = zext i8 %37 to i32 + %39 = shl i32 %38, 3 + %40 = or i32 %39, %35 + %41 = getelementptr inbounds [3 x i8], ptr %xxu, i64 0, i64 2 + %42 = load i8, ptr %41, align 1 + %43 = zext i8 %42 to i32 + %44 = shl i32 %43, 11 + %45 = or i32 %44, %40 + %46 = and i32 262143, %45 + call void (ptr, ...) @printf(ptr @.str.2, i32 %46) + ret void +} diff --git a/test/test_suite2/bitstruct/bitstruct_arrays.c3t b/test/test_suite2/bitstruct/bitstruct_arrays.c3t new file mode 100644 index 000000000..549b7d75c --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_arrays.c3t @@ -0,0 +1,1148 @@ +// #target: macos-x64 + +module foo; + +bitstruct BitField : long +{ + int a : 0..2; + int b : 3..8; + int c : 9..18; + bool d : 19; + bool e : 20; +} + +bitstruct BitField2 : char[3] +{ + int a : 0..2; + int b : 3..8; + int c : 9..18; + bool d : 19; + bool e : 20; +} + +bitstruct BitField3 : char[3] +{ + int a : 1..3; + int b : 4..9; + int c : 10..19; + bool d : 20; + bool e : 21; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + test1(); + test2(); + test3(); +} +fn void test1() +{ + BitField xx = { 2, 3, 15, true, false }; + xx.a = 3; + printf("%d, %d\n", xx.a, xx.b); + xx.a -= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b *= 2; + printf("%d, %d\n", xx.a, xx.b); + xx.b ^= 4; + printf("%d, %d\n", xx.a, xx.b); + xx.b |= 4; + printf("%d, %d\n", xx.a, xx.b); + xx.b <<= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b >>= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b /= 2; + printf("%d, %d\n", xx.a, xx.b); + xx.b %= 2; + printf("%d, %d\n", xx.a, xx.b); + xx.e = true; + printf("%d\n", xx.e); + xx.e = false; + printf("%d\n", xx.e); +} + +fn void test2() +{ + BitField2 xx = { 2, 3, 15, false, false }; + xx.a = 3; + printf("%d, %d\n", xx.a, xx.b); + xx.a -= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b *= 2; + printf("%d, %d\n", xx.a, xx.b); + xx.b ^= 4; + printf("%d, %d\n", xx.a, xx.b); + xx.b |= 4; + printf("%d, %d\n", xx.a, xx.b); + xx.b <<= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b >>= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b /= 2; + printf("%d, %d\n", xx.a, xx.b); + xx.b %= 2; + printf("%d, %d\n", xx.a, xx.b); + printf("..%d\n", xx.e); + xx.e = true; + printf("%d\n", xx.e); + xx.e = false; + printf("%d\n", xx.e); +} + +fn void test3() +{ + BitField3 xx = { 2, 3, 15, false, false }; + xx.a = 3; + printf("%d, %d\n", xx.a, xx.b); + xx.a -= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b *= 2; + printf("%d, %d\n", xx.a, xx.b); + xx.b ^= 4; + printf("%d, %d\n", xx.a, xx.b); + xx.b |= 4; + printf("%d, %d\n", xx.a, xx.b); + xx.b <<= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b >>= 1; + printf("%d, %d\n", xx.a, xx.b); + xx.b /= 2; + printf("%d, %d\n", xx.a, xx.b); + xx.b %= 2; + printf("%d, %d\n", xx.a, xx.b); + printf("..%d\n", xx.e); + xx.e = true; + printf("%d\n", xx.e); + xx.e = false; + printf("%d\n", xx.e); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + call void @foo.test1() + call void @foo.test2() + call void @foo.test3() + ret void +} + +; Function Attrs: nounwind +define void @foo.test1() #0 { +entry: + %xx = alloca i64, align 8 + store i64 531994, ptr %xx, align 8 + %0 = load i64, ptr %xx, align 8 + %1 = and i64 %0, -8 + %2 = or i64 %1, 3 + store i64 %2, ptr %xx, align 8 + %3 = load i64, ptr %xx, align 8 + %4 = shl i64 %3, 61 + %5 = ashr i64 %4, 61 + %6 = trunc i64 %5 to i32 + %7 = load i64, ptr %xx, align 8 + %8 = shl i64 %7, 55 + %9 = ashr i64 %8, 58 + %10 = trunc i64 %9 to i32 + call void (ptr, ...) @printf(ptr @.str, i32 %6, i32 %10) + %11 = load i64, ptr %xx, align 8 + %12 = shl i64 %11, 61 + %13 = ashr i64 %12, 61 + %14 = trunc i64 %13 to i32 + %sub = sub i32 %14, 1 + %15 = load i64, ptr %xx, align 8 + %16 = zext i32 %sub to i64 + %17 = and i64 %16, 7 + %18 = and i64 %15, -8 + %19 = or i64 %18, %17 + store i64 %19, ptr %xx, align 8 + %20 = load i64, ptr %xx, align 8 + %21 = shl i64 %20, 61 + %22 = ashr i64 %21, 61 + %23 = trunc i64 %22 to i32 + %24 = load i64, ptr %xx, align 8 + %25 = shl i64 %24, 55 + %26 = ashr i64 %25, 58 + %27 = trunc i64 %26 to i32 + call void (ptr, ...) @printf(ptr @.str.1, i32 %23, i32 %27) + %28 = load i64, ptr %xx, align 8 + %29 = shl i64 %28, 55 + %30 = ashr i64 %29, 58 + %31 = trunc i64 %30 to i32 + %mul = mul i32 %31, 2 + %32 = load i64, ptr %xx, align 8 + %33 = zext i32 %mul to i64 + %34 = shl i64 %33, 3 + %35 = and i64 %34, 504 + %36 = and i64 %32, -505 + %37 = or i64 %36, %35 + store i64 %37, ptr %xx, align 8 + %38 = load i64, ptr %xx, align 8 + %39 = shl i64 %38, 61 + %40 = ashr i64 %39, 61 + %41 = trunc i64 %40 to i32 + %42 = load i64, ptr %xx, align 8 + %43 = shl i64 %42, 55 + %44 = ashr i64 %43, 58 + %45 = trunc i64 %44 to i32 + call void (ptr, ...) @printf(ptr @.str.2, i32 %41, i32 %45) + %46 = load i64, ptr %xx, align 8 + %47 = shl i64 %46, 55 + %48 = ashr i64 %47, 58 + %49 = trunc i64 %48 to i32 + %xor = xor i32 %49, 4 + %50 = load i64, ptr %xx, align 8 + %51 = zext i32 %xor to i64 + %52 = shl i64 %51, 3 + %53 = and i64 %52, 504 + %54 = and i64 %50, -505 + %55 = or i64 %54, %53 + store i64 %55, ptr %xx, align 8 + %56 = load i64, ptr %xx, align 8 + %57 = shl i64 %56, 61 + %58 = ashr i64 %57, 61 + %59 = trunc i64 %58 to i32 + %60 = load i64, ptr %xx, align 8 + %61 = shl i64 %60, 55 + %62 = ashr i64 %61, 58 + %63 = trunc i64 %62 to i32 + call void (ptr, ...) @printf(ptr @.str.3, i32 %59, i32 %63) + %64 = load i64, ptr %xx, align 8 + %65 = shl i64 %64, 55 + %66 = ashr i64 %65, 58 + %67 = trunc i64 %66 to i32 + %or = or i32 %67, 4 + %68 = load i64, ptr %xx, align 8 + %69 = zext i32 %or to i64 + %70 = shl i64 %69, 3 + %71 = and i64 %70, 504 + %72 = and i64 %68, -505 + %73 = or i64 %72, %71 + store i64 %73, ptr %xx, align 8 + %74 = load i64, ptr %xx, align 8 + %75 = shl i64 %74, 61 + %76 = ashr i64 %75, 61 + %77 = trunc i64 %76 to i32 + %78 = load i64, ptr %xx, align 8 + %79 = shl i64 %78, 55 + %80 = ashr i64 %79, 58 + %81 = trunc i64 %80 to i32 + call void (ptr, ...) @printf(ptr @.str.4, i32 %77, i32 %81) + %82 = load i64, ptr %xx, align 8 + %83 = shl i64 %82, 55 + %84 = ashr i64 %83, 58 + %85 = trunc i64 %84 to i32 + %shl = shl i32 %85, 1 + %86 = freeze i32 %shl + %87 = load i64, ptr %xx, align 8 + %88 = zext i32 %86 to i64 + %89 = shl i64 %88, 3 + %90 = and i64 %89, 504 + %91 = and i64 %87, -505 + %92 = or i64 %91, %90 + store i64 %92, ptr %xx, align 8 + %93 = load i64, ptr %xx, align 8 + %94 = shl i64 %93, 61 + %95 = ashr i64 %94, 61 + %96 = trunc i64 %95 to i32 + %97 = load i64, ptr %xx, align 8 + %98 = shl i64 %97, 55 + %99 = ashr i64 %98, 58 + %100 = trunc i64 %99 to i32 + call void (ptr, ...) @printf(ptr @.str.5, i32 %96, i32 %100) + %101 = load i64, ptr %xx, align 8 + %102 = shl i64 %101, 55 + %103 = ashr i64 %102, 58 + %104 = trunc i64 %103 to i32 + %ashr = ashr i32 %104, 1 + %105 = freeze i32 %ashr + %106 = load i64, ptr %xx, align 8 + %107 = zext i32 %105 to i64 + %108 = shl i64 %107, 3 + %109 = and i64 %108, 504 + %110 = and i64 %106, -505 + %111 = or i64 %110, %109 + store i64 %111, ptr %xx, align 8 + %112 = load i64, ptr %xx, align 8 + %113 = shl i64 %112, 61 + %114 = ashr i64 %113, 61 + %115 = trunc i64 %114 to i32 + %116 = load i64, ptr %xx, align 8 + %117 = shl i64 %116, 55 + %118 = ashr i64 %117, 58 + %119 = trunc i64 %118 to i32 + call void (ptr, ...) @printf(ptr @.str.6, i32 %115, i32 %119) + %120 = load i64, ptr %xx, align 8 + %121 = shl i64 %120, 55 + %122 = ashr i64 %121, 58 + %123 = trunc i64 %122 to i32 + %sdiv = sdiv i32 %123, 2 + %124 = load i64, ptr %xx, align 8 + %125 = zext i32 %sdiv to i64 + %126 = shl i64 %125, 3 + %127 = and i64 %126, 504 + %128 = and i64 %124, -505 + %129 = or i64 %128, %127 + store i64 %129, ptr %xx, align 8 + %130 = load i64, ptr %xx, align 8 + %131 = shl i64 %130, 61 + %132 = ashr i64 %131, 61 + %133 = trunc i64 %132 to i32 + %134 = load i64, ptr %xx, align 8 + %135 = shl i64 %134, 55 + %136 = ashr i64 %135, 58 + %137 = trunc i64 %136 to i32 + call void (ptr, ...) @printf(ptr @.str.7, i32 %133, i32 %137) + %138 = load i64, ptr %xx, align 8 + %139 = shl i64 %138, 55 + %140 = ashr i64 %139, 58 + %141 = trunc i64 %140 to i32 + %smod = srem i32 %141, 2 + %142 = load i64, ptr %xx, align 8 + %143 = zext i32 %smod to i64 + %144 = shl i64 %143, 3 + %145 = and i64 %144, 504 + %146 = and i64 %142, -505 + %147 = or i64 %146, %145 + store i64 %147, ptr %xx, align 8 + %148 = load i64, ptr %xx, align 8 + %149 = shl i64 %148, 61 + %150 = ashr i64 %149, 61 + %151 = trunc i64 %150 to i32 + %152 = load i64, ptr %xx, align 8 + %153 = shl i64 %152, 55 + %154 = ashr i64 %153, 58 + %155 = trunc i64 %154 to i32 + call void (ptr, ...) @printf(ptr @.str.8, i32 %151, i32 %155) + %156 = load i64, ptr %xx, align 8 + %157 = and i64 %156, -1048577 + %158 = or i64 %157, 1048576 + store i64 %158, ptr %xx, align 8 + %159 = load i64, ptr %xx, align 8 + %160 = lshr i64 %159, 20 + %161 = and i64 1, %160 + %162 = trunc i64 %161 to i8 + %163 = trunc i8 %162 to i1 + %boolsi = zext i1 %163 to i32 + call void (ptr, ...) @printf(ptr @.str.9, i32 %boolsi) + %164 = load i64, ptr %xx, align 8 + %165 = and i64 %164, -1048577 + store i64 %165, ptr %xx, align 8 + %166 = load i64, ptr %xx, align 8 + %167 = lshr i64 %166, 20 + %168 = and i64 1, %167 + %169 = trunc i64 %168 to i8 + %170 = trunc i8 %169 to i1 + %boolsi1 = zext i1 %170 to i32 + call void (ptr, ...) @printf(ptr @.str.10, i32 %boolsi1) + ret void +} + +; Function Attrs: nounwind +define void @foo.test2() #0 { +entry: + %xx = alloca [3 x i8], align 1 + store [3 x i8] c"\1A\1E\00", ptr %xx, align 1 + %0 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %1 = load i8, ptr %0, align 1 + %2 = and i8 %1, -8 + %3 = or i8 %2, 3 + store i8 %3, ptr %0, align 1 + %4 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %5 = load i8, ptr %4, align 1 + %6 = zext i8 %5 to i32 + %7 = shl i32 %6, 29 + %8 = ashr i32 %7, 29 + %9 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %10 = load i8, ptr %9, align 1 + %11 = zext i8 %10 to i32 + %12 = lshr i32 %11, 3 + %13 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %14 = load i8, ptr %13, align 1 + %15 = zext i8 %14 to i32 + %16 = shl i32 %15, 5 + %17 = or i32 %16, %12 + %18 = shl i32 %17, 26 + %19 = ashr i32 %18, 26 + call void (ptr, ...) @printf(ptr @.str.11, i32 %8, i32 %19) + %20 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %21 = load i8, ptr %20, align 1 + %22 = zext i8 %21 to i32 + %23 = shl i32 %22, 29 + %24 = ashr i32 %23, 29 + %sub = sub i32 %24, 1 + %25 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %26 = trunc i32 %sub to i8 + %27 = and i8 %26, 7 + %28 = load i8, ptr %25, align 1 + %29 = and i8 %28, -8 + %30 = or i8 %29, %27 + store i8 %30, ptr %25, align 1 + %31 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %32 = load i8, ptr %31, align 1 + %33 = zext i8 %32 to i32 + %34 = shl i32 %33, 29 + %35 = ashr i32 %34, 29 + %36 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %37 = load i8, ptr %36, align 1 + %38 = zext i8 %37 to i32 + %39 = lshr i32 %38, 3 + %40 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %41 = load i8, ptr %40, align 1 + %42 = zext i8 %41 to i32 + %43 = shl i32 %42, 5 + %44 = or i32 %43, %39 + %45 = shl i32 %44, 26 + %46 = ashr i32 %45, 26 + call void (ptr, ...) @printf(ptr @.str.12, i32 %35, i32 %46) + %47 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %48 = load i8, ptr %47, align 1 + %49 = zext i8 %48 to i32 + %50 = lshr i32 %49, 3 + %51 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %52 = load i8, ptr %51, align 1 + %53 = zext i8 %52 to i32 + %54 = shl i32 %53, 5 + %55 = or i32 %54, %50 + %56 = shl i32 %55, 26 + %57 = ashr i32 %56, 26 + %mul = mul i32 %57, 2 + %58 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %59 = shl i32 %mul, 3 + %60 = trunc i32 %59 to i8 + %61 = load i8, ptr %58, align 1 + %62 = and i8 %61, 7 + %63 = or i8 %62, %60 + store i8 %63, ptr %58, align 1 + %64 = lshr i32 %mul, 5 + %65 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %66 = trunc i32 %64 to i8 + %67 = and i8 %66, 1 + %68 = load i8, ptr %65, align 1 + %69 = and i8 %68, -2 + %70 = or i8 %69, %67 + store i8 %70, ptr %65, align 1 + %71 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %72 = load i8, ptr %71, align 1 + %73 = zext i8 %72 to i32 + %74 = shl i32 %73, 29 + %75 = ashr i32 %74, 29 + %76 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %77 = load i8, ptr %76, align 1 + %78 = zext i8 %77 to i32 + %79 = lshr i32 %78, 3 + %80 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %81 = load i8, ptr %80, align 1 + %82 = zext i8 %81 to i32 + %83 = shl i32 %82, 5 + %84 = or i32 %83, %79 + %85 = shl i32 %84, 26 + %86 = ashr i32 %85, 26 + call void (ptr, ...) @printf(ptr @.str.13, i32 %75, i32 %86) + %87 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %88 = load i8, ptr %87, align 1 + %89 = zext i8 %88 to i32 + %90 = lshr i32 %89, 3 + %91 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %92 = load i8, ptr %91, align 1 + %93 = zext i8 %92 to i32 + %94 = shl i32 %93, 5 + %95 = or i32 %94, %90 + %96 = shl i32 %95, 26 + %97 = ashr i32 %96, 26 + %xor = xor i32 %97, 4 + %98 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %99 = shl i32 %xor, 3 + %100 = trunc i32 %99 to i8 + %101 = load i8, ptr %98, align 1 + %102 = and i8 %101, 7 + %103 = or i8 %102, %100 + store i8 %103, ptr %98, align 1 + %104 = lshr i32 %xor, 5 + %105 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %106 = trunc i32 %104 to i8 + %107 = and i8 %106, 1 + %108 = load i8, ptr %105, align 1 + %109 = and i8 %108, -2 + %110 = or i8 %109, %107 + store i8 %110, ptr %105, align 1 + %111 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %112 = load i8, ptr %111, align 1 + %113 = zext i8 %112 to i32 + %114 = shl i32 %113, 29 + %115 = ashr i32 %114, 29 + %116 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %117 = load i8, ptr %116, align 1 + %118 = zext i8 %117 to i32 + %119 = lshr i32 %118, 3 + %120 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %121 = load i8, ptr %120, align 1 + %122 = zext i8 %121 to i32 + %123 = shl i32 %122, 5 + %124 = or i32 %123, %119 + %125 = shl i32 %124, 26 + %126 = ashr i32 %125, 26 + call void (ptr, ...) @printf(ptr @.str.14, i32 %115, i32 %126) + %127 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %128 = load i8, ptr %127, align 1 + %129 = zext i8 %128 to i32 + %130 = lshr i32 %129, 3 + %131 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %132 = load i8, ptr %131, align 1 + %133 = zext i8 %132 to i32 + %134 = shl i32 %133, 5 + %135 = or i32 %134, %130 + %136 = shl i32 %135, 26 + %137 = ashr i32 %136, 26 + %or = or i32 %137, 4 + %138 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %139 = shl i32 %or, 3 + %140 = trunc i32 %139 to i8 + %141 = load i8, ptr %138, align 1 + %142 = and i8 %141, 7 + %143 = or i8 %142, %140 + store i8 %143, ptr %138, align 1 + %144 = lshr i32 %or, 5 + %145 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %146 = trunc i32 %144 to i8 + %147 = and i8 %146, 1 + %148 = load i8, ptr %145, align 1 + %149 = and i8 %148, -2 + %150 = or i8 %149, %147 + store i8 %150, ptr %145, align 1 + %151 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %152 = load i8, ptr %151, align 1 + %153 = zext i8 %152 to i32 + %154 = shl i32 %153, 29 + %155 = ashr i32 %154, 29 + %156 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %157 = load i8, ptr %156, align 1 + %158 = zext i8 %157 to i32 + %159 = lshr i32 %158, 3 + %160 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %161 = load i8, ptr %160, align 1 + %162 = zext i8 %161 to i32 + %163 = shl i32 %162, 5 + %164 = or i32 %163, %159 + %165 = shl i32 %164, 26 + %166 = ashr i32 %165, 26 + call void (ptr, ...) @printf(ptr @.str.15, i32 %155, i32 %166) + %167 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %168 = load i8, ptr %167, align 1 + %169 = zext i8 %168 to i32 + %170 = lshr i32 %169, 3 + %171 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %172 = load i8, ptr %171, align 1 + %173 = zext i8 %172 to i32 + %174 = shl i32 %173, 5 + %175 = or i32 %174, %170 + %176 = shl i32 %175, 26 + %177 = ashr i32 %176, 26 + %shl = shl i32 %177, 1 + %178 = freeze i32 %shl + %179 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %180 = shl i32 %178, 3 + %181 = trunc i32 %180 to i8 + %182 = load i8, ptr %179, align 1 + %183 = and i8 %182, 7 + %184 = or i8 %183, %181 + store i8 %184, ptr %179, align 1 + %185 = lshr i32 %178, 5 + %186 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %187 = trunc i32 %185 to i8 + %188 = and i8 %187, 1 + %189 = load i8, ptr %186, align 1 + %190 = and i8 %189, -2 + %191 = or i8 %190, %188 + store i8 %191, ptr %186, align 1 + %192 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %193 = load i8, ptr %192, align 1 + %194 = zext i8 %193 to i32 + %195 = shl i32 %194, 29 + %196 = ashr i32 %195, 29 + %197 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %198 = load i8, ptr %197, align 1 + %199 = zext i8 %198 to i32 + %200 = lshr i32 %199, 3 + %201 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %202 = load i8, ptr %201, align 1 + %203 = zext i8 %202 to i32 + %204 = shl i32 %203, 5 + %205 = or i32 %204, %200 + %206 = shl i32 %205, 26 + %207 = ashr i32 %206, 26 + call void (ptr, ...) @printf(ptr @.str.16, i32 %196, i32 %207) + %208 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %209 = load i8, ptr %208, align 1 + %210 = zext i8 %209 to i32 + %211 = lshr i32 %210, 3 + %212 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %213 = load i8, ptr %212, align 1 + %214 = zext i8 %213 to i32 + %215 = shl i32 %214, 5 + %216 = or i32 %215, %211 + %217 = shl i32 %216, 26 + %218 = ashr i32 %217, 26 + %ashr = ashr i32 %218, 1 + %219 = freeze i32 %ashr + %220 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %221 = shl i32 %219, 3 + %222 = trunc i32 %221 to i8 + %223 = load i8, ptr %220, align 1 + %224 = and i8 %223, 7 + %225 = or i8 %224, %222 + store i8 %225, ptr %220, align 1 + %226 = lshr i32 %219, 5 + %227 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %228 = trunc i32 %226 to i8 + %229 = and i8 %228, 1 + %230 = load i8, ptr %227, align 1 + %231 = and i8 %230, -2 + %232 = or i8 %231, %229 + store i8 %232, ptr %227, align 1 + %233 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %234 = load i8, ptr %233, align 1 + %235 = zext i8 %234 to i32 + %236 = shl i32 %235, 29 + %237 = ashr i32 %236, 29 + %238 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %239 = load i8, ptr %238, align 1 + %240 = zext i8 %239 to i32 + %241 = lshr i32 %240, 3 + %242 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %243 = load i8, ptr %242, align 1 + %244 = zext i8 %243 to i32 + %245 = shl i32 %244, 5 + %246 = or i32 %245, %241 + %247 = shl i32 %246, 26 + %248 = ashr i32 %247, 26 + call void (ptr, ...) @printf(ptr @.str.17, i32 %237, i32 %248) + %249 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %250 = load i8, ptr %249, align 1 + %251 = zext i8 %250 to i32 + %252 = lshr i32 %251, 3 + %253 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %254 = load i8, ptr %253, align 1 + %255 = zext i8 %254 to i32 + %256 = shl i32 %255, 5 + %257 = or i32 %256, %252 + %258 = shl i32 %257, 26 + %259 = ashr i32 %258, 26 + %sdiv = sdiv i32 %259, 2 + %260 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %261 = shl i32 %sdiv, 3 + %262 = trunc i32 %261 to i8 + %263 = load i8, ptr %260, align 1 + %264 = and i8 %263, 7 + %265 = or i8 %264, %262 + store i8 %265, ptr %260, align 1 + %266 = lshr i32 %sdiv, 5 + %267 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %268 = trunc i32 %266 to i8 + %269 = and i8 %268, 1 + %270 = load i8, ptr %267, align 1 + %271 = and i8 %270, -2 + %272 = or i8 %271, %269 + store i8 %272, ptr %267, align 1 + %273 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %274 = load i8, ptr %273, align 1 + %275 = zext i8 %274 to i32 + %276 = shl i32 %275, 29 + %277 = ashr i32 %276, 29 + %278 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %279 = load i8, ptr %278, align 1 + %280 = zext i8 %279 to i32 + %281 = lshr i32 %280, 3 + %282 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %283 = load i8, ptr %282, align 1 + %284 = zext i8 %283 to i32 + %285 = shl i32 %284, 5 + %286 = or i32 %285, %281 + %287 = shl i32 %286, 26 + %288 = ashr i32 %287, 26 + call void (ptr, ...) @printf(ptr @.str.18, i32 %277, i32 %288) + %289 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %290 = load i8, ptr %289, align 1 + %291 = zext i8 %290 to i32 + %292 = lshr i32 %291, 3 + %293 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %294 = load i8, ptr %293, align 1 + %295 = zext i8 %294 to i32 + %296 = shl i32 %295, 5 + %297 = or i32 %296, %292 + %298 = shl i32 %297, 26 + %299 = ashr i32 %298, 26 + %smod = srem i32 %299, 2 + %300 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %301 = shl i32 %smod, 3 + %302 = trunc i32 %301 to i8 + %303 = load i8, ptr %300, align 1 + %304 = and i8 %303, 7 + %305 = or i8 %304, %302 + store i8 %305, ptr %300, align 1 + %306 = lshr i32 %smod, 5 + %307 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %308 = trunc i32 %306 to i8 + %309 = and i8 %308, 1 + %310 = load i8, ptr %307, align 1 + %311 = and i8 %310, -2 + %312 = or i8 %311, %309 + store i8 %312, ptr %307, align 1 + %313 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %314 = load i8, ptr %313, align 1 + %315 = zext i8 %314 to i32 + %316 = shl i32 %315, 29 + %317 = ashr i32 %316, 29 + %318 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %319 = load i8, ptr %318, align 1 + %320 = zext i8 %319 to i32 + %321 = lshr i32 %320, 3 + %322 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %323 = load i8, ptr %322, align 1 + %324 = zext i8 %323 to i32 + %325 = shl i32 %324, 5 + %326 = or i32 %325, %321 + %327 = shl i32 %326, 26 + %328 = ashr i32 %327, 26 + call void (ptr, ...) @printf(ptr @.str.19, i32 %317, i32 %328) + %329 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %330 = load i8, ptr %329, align 1 + %331 = lshr i8 %330, 4 + %332 = trunc i8 %331 to i1 + %boolsi = zext i1 %332 to i32 + call void (ptr, ...) @printf(ptr @.str.20, i32 %boolsi) + %333 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %334 = load i8, ptr %333, align 1 + %335 = and i8 %334, -17 + %336 = or i8 %335, 16 + store i8 %336, ptr %333, align 1 + %337 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %338 = load i8, ptr %337, align 1 + %339 = lshr i8 %338, 4 + %340 = trunc i8 %339 to i1 + %boolsi1 = zext i1 %340 to i32 + call void (ptr, ...) @printf(ptr @.str.21, i32 %boolsi1) + %341 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %342 = load i8, ptr %341, align 1 + %343 = and i8 %342, -17 + store i8 %343, ptr %341, align 1 + %344 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %345 = load i8, ptr %344, align 1 + %346 = lshr i8 %345, 4 + %347 = trunc i8 %346 to i1 + %boolsi2 = zext i1 %347 to i32 + call void (ptr, ...) @printf(ptr @.str.22, i32 %boolsi2) + ret void +} + +; Function Attrs: nounwind +define void @foo.test3() #0 { +entry: + %xx = alloca [3 x i8], align 1 + store [3 x i8] c"4<\00", ptr %xx, align 1 + %0 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %1 = load i8, ptr %0, align 1 + %2 = and i8 %1, -15 + %3 = or i8 %2, 6 + store i8 %3, ptr %0, align 1 + %4 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %5 = load i8, ptr %4, align 1 + %6 = zext i8 %5 to i32 + %7 = lshr i32 %6, 1 + %8 = shl i32 %7, 29 + %9 = ashr i32 %8, 29 + %10 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %11 = load i8, ptr %10, align 1 + %12 = zext i8 %11 to i32 + %13 = lshr i32 %12, 4 + %14 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %15 = load i8, ptr %14, align 1 + %16 = zext i8 %15 to i32 + %17 = shl i32 %16, 4 + %18 = or i32 %17, %13 + %19 = shl i32 %18, 26 + %20 = ashr i32 %19, 26 + call void (ptr, ...) @printf(ptr @.str.23, i32 %9, i32 %20) + %21 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %22 = load i8, ptr %21, align 1 + %23 = zext i8 %22 to i32 + %24 = lshr i32 %23, 1 + %25 = shl i32 %24, 29 + %26 = ashr i32 %25, 29 + %sub = sub i32 %26, 1 + %27 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %28 = shl i32 %sub, 1 + %29 = trunc i32 %28 to i8 + %30 = and i8 %29, 15 + %31 = load i8, ptr %27, align 1 + %32 = and i8 %31, -15 + %33 = or i8 %32, %30 + store i8 %33, ptr %27, align 1 + %34 = lshr i32 %sub, 7 + %35 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %36 = load i8, ptr %35, align 1 + %37 = zext i8 %36 to i32 + %38 = lshr i32 %37, 1 + %39 = shl i32 %38, 29 + %40 = ashr i32 %39, 29 + %41 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %42 = load i8, ptr %41, align 1 + %43 = zext i8 %42 to i32 + %44 = lshr i32 %43, 4 + %45 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %46 = load i8, ptr %45, align 1 + %47 = zext i8 %46 to i32 + %48 = shl i32 %47, 4 + %49 = or i32 %48, %44 + %50 = shl i32 %49, 26 + %51 = ashr i32 %50, 26 + call void (ptr, ...) @printf(ptr @.str.24, i32 %40, i32 %51) + %52 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %53 = load i8, ptr %52, align 1 + %54 = zext i8 %53 to i32 + %55 = lshr i32 %54, 4 + %56 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %57 = load i8, ptr %56, align 1 + %58 = zext i8 %57 to i32 + %59 = shl i32 %58, 4 + %60 = or i32 %59, %55 + %61 = shl i32 %60, 26 + %62 = ashr i32 %61, 26 + %mul = mul i32 %62, 2 + %63 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %64 = shl i32 %mul, 4 + %65 = trunc i32 %64 to i8 + %66 = load i8, ptr %63, align 1 + %67 = and i8 %66, 15 + %68 = or i8 %67, %65 + store i8 %68, ptr %63, align 1 + %69 = lshr i32 %mul, 4 + %70 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %71 = trunc i32 %69 to i8 + %72 = and i8 %71, 3 + %73 = load i8, ptr %70, align 1 + %74 = and i8 %73, -4 + %75 = or i8 %74, %72 + store i8 %75, ptr %70, align 1 + %76 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %77 = load i8, ptr %76, align 1 + %78 = zext i8 %77 to i32 + %79 = lshr i32 %78, 1 + %80 = shl i32 %79, 29 + %81 = ashr i32 %80, 29 + %82 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %83 = load i8, ptr %82, align 1 + %84 = zext i8 %83 to i32 + %85 = lshr i32 %84, 4 + %86 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %87 = load i8, ptr %86, align 1 + %88 = zext i8 %87 to i32 + %89 = shl i32 %88, 4 + %90 = or i32 %89, %85 + %91 = shl i32 %90, 26 + %92 = ashr i32 %91, 26 + call void (ptr, ...) @printf(ptr @.str.25, i32 %81, i32 %92) + %93 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %94 = load i8, ptr %93, align 1 + %95 = zext i8 %94 to i32 + %96 = lshr i32 %95, 4 + %97 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %98 = load i8, ptr %97, align 1 + %99 = zext i8 %98 to i32 + %100 = shl i32 %99, 4 + %101 = or i32 %100, %96 + %102 = shl i32 %101, 26 + %103 = ashr i32 %102, 26 + %xor = xor i32 %103, 4 + %104 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %105 = shl i32 %xor, 4 + %106 = trunc i32 %105 to i8 + %107 = load i8, ptr %104, align 1 + %108 = and i8 %107, 15 + %109 = or i8 %108, %106 + store i8 %109, ptr %104, align 1 + %110 = lshr i32 %xor, 4 + %111 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %112 = trunc i32 %110 to i8 + %113 = and i8 %112, 3 + %114 = load i8, ptr %111, align 1 + %115 = and i8 %114, -4 + %116 = or i8 %115, %113 + store i8 %116, ptr %111, align 1 + %117 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %118 = load i8, ptr %117, align 1 + %119 = zext i8 %118 to i32 + %120 = lshr i32 %119, 1 + %121 = shl i32 %120, 29 + %122 = ashr i32 %121, 29 + %123 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %124 = load i8, ptr %123, align 1 + %125 = zext i8 %124 to i32 + %126 = lshr i32 %125, 4 + %127 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %128 = load i8, ptr %127, align 1 + %129 = zext i8 %128 to i32 + %130 = shl i32 %129, 4 + %131 = or i32 %130, %126 + %132 = shl i32 %131, 26 + %133 = ashr i32 %132, 26 + call void (ptr, ...) @printf(ptr @.str.26, i32 %122, i32 %133) + %134 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %135 = load i8, ptr %134, align 1 + %136 = zext i8 %135 to i32 + %137 = lshr i32 %136, 4 + %138 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %139 = load i8, ptr %138, align 1 + %140 = zext i8 %139 to i32 + %141 = shl i32 %140, 4 + %142 = or i32 %141, %137 + %143 = shl i32 %142, 26 + %144 = ashr i32 %143, 26 + %or = or i32 %144, 4 + %145 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %146 = shl i32 %or, 4 + %147 = trunc i32 %146 to i8 + %148 = load i8, ptr %145, align 1 + %149 = and i8 %148, 15 + %150 = or i8 %149, %147 + store i8 %150, ptr %145, align 1 + %151 = lshr i32 %or, 4 + %152 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %153 = trunc i32 %151 to i8 + %154 = and i8 %153, 3 + %155 = load i8, ptr %152, align 1 + %156 = and i8 %155, -4 + %157 = or i8 %156, %154 + store i8 %157, ptr %152, align 1 + %158 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %159 = load i8, ptr %158, align 1 + %160 = zext i8 %159 to i32 + %161 = lshr i32 %160, 1 + %162 = shl i32 %161, 29 + %163 = ashr i32 %162, 29 + %164 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %165 = load i8, ptr %164, align 1 + %166 = zext i8 %165 to i32 + %167 = lshr i32 %166, 4 + %168 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %169 = load i8, ptr %168, align 1 + %170 = zext i8 %169 to i32 + %171 = shl i32 %170, 4 + %172 = or i32 %171, %167 + %173 = shl i32 %172, 26 + %174 = ashr i32 %173, 26 + call void (ptr, ...) @printf(ptr @.str.27, i32 %163, i32 %174) + %175 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %176 = load i8, ptr %175, align 1 + %177 = zext i8 %176 to i32 + %178 = lshr i32 %177, 4 + %179 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %180 = load i8, ptr %179, align 1 + %181 = zext i8 %180 to i32 + %182 = shl i32 %181, 4 + %183 = or i32 %182, %178 + %184 = shl i32 %183, 26 + %185 = ashr i32 %184, 26 + %shl = shl i32 %185, 1 + %186 = freeze i32 %shl + %187 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %188 = shl i32 %186, 4 + %189 = trunc i32 %188 to i8 + %190 = load i8, ptr %187, align 1 + %191 = and i8 %190, 15 + %192 = or i8 %191, %189 + store i8 %192, ptr %187, align 1 + %193 = lshr i32 %186, 4 + %194 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %195 = trunc i32 %193 to i8 + %196 = and i8 %195, 3 + %197 = load i8, ptr %194, align 1 + %198 = and i8 %197, -4 + %199 = or i8 %198, %196 + store i8 %199, ptr %194, align 1 + %200 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %201 = load i8, ptr %200, align 1 + %202 = zext i8 %201 to i32 + %203 = lshr i32 %202, 1 + %204 = shl i32 %203, 29 + %205 = ashr i32 %204, 29 + %206 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %207 = load i8, ptr %206, align 1 + %208 = zext i8 %207 to i32 + %209 = lshr i32 %208, 4 + %210 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %211 = load i8, ptr %210, align 1 + %212 = zext i8 %211 to i32 + %213 = shl i32 %212, 4 + %214 = or i32 %213, %209 + %215 = shl i32 %214, 26 + %216 = ashr i32 %215, 26 + call void (ptr, ...) @printf(ptr @.str.28, i32 %205, i32 %216) + %217 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %218 = load i8, ptr %217, align 1 + %219 = zext i8 %218 to i32 + %220 = lshr i32 %219, 4 + %221 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %222 = load i8, ptr %221, align 1 + %223 = zext i8 %222 to i32 + %224 = shl i32 %223, 4 + %225 = or i32 %224, %220 + %226 = shl i32 %225, 26 + %227 = ashr i32 %226, 26 + %ashr = ashr i32 %227, 1 + %228 = freeze i32 %ashr + %229 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %230 = shl i32 %228, 4 + %231 = trunc i32 %230 to i8 + %232 = load i8, ptr %229, align 1 + %233 = and i8 %232, 15 + %234 = or i8 %233, %231 + store i8 %234, ptr %229, align 1 + %235 = lshr i32 %228, 4 + %236 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %237 = trunc i32 %235 to i8 + %238 = and i8 %237, 3 + %239 = load i8, ptr %236, align 1 + %240 = and i8 %239, -4 + %241 = or i8 %240, %238 + store i8 %241, ptr %236, align 1 + %242 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %243 = load i8, ptr %242, align 1 + %244 = zext i8 %243 to i32 + %245 = lshr i32 %244, 1 + %246 = shl i32 %245, 29 + %247 = ashr i32 %246, 29 + %248 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %249 = load i8, ptr %248, align 1 + %250 = zext i8 %249 to i32 + %251 = lshr i32 %250, 4 + %252 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %253 = load i8, ptr %252, align 1 + %254 = zext i8 %253 to i32 + %255 = shl i32 %254, 4 + %256 = or i32 %255, %251 + %257 = shl i32 %256, 26 + %258 = ashr i32 %257, 26 + call void (ptr, ...) @printf(ptr @.str.29, i32 %247, i32 %258) + %259 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %260 = load i8, ptr %259, align 1 + %261 = zext i8 %260 to i32 + %262 = lshr i32 %261, 4 + %263 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %264 = load i8, ptr %263, align 1 + %265 = zext i8 %264 to i32 + %266 = shl i32 %265, 4 + %267 = or i32 %266, %262 + %268 = shl i32 %267, 26 + %269 = ashr i32 %268, 26 + %sdiv = sdiv i32 %269, 2 + %270 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %271 = shl i32 %sdiv, 4 + %272 = trunc i32 %271 to i8 + %273 = load i8, ptr %270, align 1 + %274 = and i8 %273, 15 + %275 = or i8 %274, %272 + store i8 %275, ptr %270, align 1 + %276 = lshr i32 %sdiv, 4 + %277 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %278 = trunc i32 %276 to i8 + %279 = and i8 %278, 3 + %280 = load i8, ptr %277, align 1 + %281 = and i8 %280, -4 + %282 = or i8 %281, %279 + store i8 %282, ptr %277, align 1 + %283 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %284 = load i8, ptr %283, align 1 + %285 = zext i8 %284 to i32 + %286 = lshr i32 %285, 1 + %287 = shl i32 %286, 29 + %288 = ashr i32 %287, 29 + %289 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %290 = load i8, ptr %289, align 1 + %291 = zext i8 %290 to i32 + %292 = lshr i32 %291, 4 + %293 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %294 = load i8, ptr %293, align 1 + %295 = zext i8 %294 to i32 + %296 = shl i32 %295, 4 + %297 = or i32 %296, %292 + %298 = shl i32 %297, 26 + %299 = ashr i32 %298, 26 + call void (ptr, ...) @printf(ptr @.str.30, i32 %288, i32 %299) + %300 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %301 = load i8, ptr %300, align 1 + %302 = zext i8 %301 to i32 + %303 = lshr i32 %302, 4 + %304 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %305 = load i8, ptr %304, align 1 + %306 = zext i8 %305 to i32 + %307 = shl i32 %306, 4 + %308 = or i32 %307, %303 + %309 = shl i32 %308, 26 + %310 = ashr i32 %309, 26 + %smod = srem i32 %310, 2 + %311 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %312 = shl i32 %smod, 4 + %313 = trunc i32 %312 to i8 + %314 = load i8, ptr %311, align 1 + %315 = and i8 %314, 15 + %316 = or i8 %315, %313 + store i8 %316, ptr %311, align 1 + %317 = lshr i32 %smod, 4 + %318 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %319 = trunc i32 %317 to i8 + %320 = and i8 %319, 3 + %321 = load i8, ptr %318, align 1 + %322 = and i8 %321, -4 + %323 = or i8 %322, %320 + store i8 %323, ptr %318, align 1 + %324 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %325 = load i8, ptr %324, align 1 + %326 = zext i8 %325 to i32 + %327 = lshr i32 %326, 1 + %328 = shl i32 %327, 29 + %329 = ashr i32 %328, 29 + %330 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 + %331 = load i8, ptr %330, align 1 + %332 = zext i8 %331 to i32 + %333 = lshr i32 %332, 4 + %334 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 1 + %335 = load i8, ptr %334, align 1 + %336 = zext i8 %335 to i32 + %337 = shl i32 %336, 4 + %338 = or i32 %337, %333 + %339 = shl i32 %338, 26 + %340 = ashr i32 %339, 26 + call void (ptr, ...) @printf(ptr @.str.31, i32 %329, i32 %340) + %341 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %342 = load i8, ptr %341, align 1 + %343 = lshr i8 %342, 5 + %344 = trunc i8 %343 to i1 + %boolsi = zext i1 %344 to i32 + call void (ptr, ...) @printf(ptr @.str.32, i32 %boolsi) + %345 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %346 = load i8, ptr %345, align 1 + %347 = and i8 %346, -33 + %348 = or i8 %347, 32 + store i8 %348, ptr %345, align 1 + %349 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %350 = load i8, ptr %349, align 1 + %351 = lshr i8 %350, 5 + %352 = trunc i8 %351 to i1 + %boolsi1 = zext i1 %352 to i32 + call void (ptr, ...) @printf(ptr @.str.33, i32 %boolsi1) + %353 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %354 = load i8, ptr %353, align 1 + %355 = and i8 %354, -33 + store i8 %355, ptr %353, align 1 + %356 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 2 + %357 = load i8, ptr %356, align 1 + %358 = lshr i8 %357, 5 + %359 = trunc i8 %358 to i1 + %boolsi2 = zext i1 %359 to i32 + call void (ptr, ...) @printf(ptr @.str.34, i32 %boolsi2) + ret void +} diff --git a/test/test_suite2/bitstruct/bitstruct_arrays_be.c3t b/test/test_suite2/bitstruct/bitstruct_arrays_be.c3t new file mode 100644 index 000000000..9da77abe2 --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_arrays_be.c3t @@ -0,0 +1,144 @@ +// #target: macos-x64 +module foo; + +module foo; + +bitstruct BitField3 : char[4] @bigendian +{ + uint c : 4..19; +} + +bitstruct BitField4 : char[4] +{ + uint c : 4..19; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + test3(); +} +fn void test3() +{ + //BitField3 xx = { 0xdeadbeef }; + BitField3 xx = { 0xbeaf }; + printf("%x = beaf\n", xx.c); + BitField4 xy = { 0xbeaf }; + void *abc = &xy; + char[4]* z = abc; + printf("%x = beaf\n", xy.c); + xy.c = 0xbeef; + printf("%x = beef\n", xy.c); + xx.c = 0xbeef; + printf("%x = beef\n", xx.c); +} + + +/* #expect: foo.ll + +define void @foo.test3() #0 { +entry: + %xx = alloca [4 x i8], align 1 + %xy = alloca [4 x i8], align 1 + %abc = alloca ptr, align 8 + %z = alloca ptr, align 8 + store [4 x i8] c"\E0\FB\0A\00", ptr %xx, align 1 + %0 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 0 + %1 = load i8, ptr %0, align 1 + %2 = zext i8 %1 to i32 + %3 = lshr i32 %2, 4 + %4 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 1 + %5 = load i8, ptr %4, align 1 + %6 = zext i8 %5 to i32 + %7 = shl i32 %6, 4 + %8 = or i32 %7, %3 + %9 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 2 + %10 = load i8, ptr %9, align 1 + %11 = zext i8 %10 to i32 + %12 = shl i32 %11, 12 + %13 = or i32 %12, %8 + %14 = shl i32 %13, 16 + %15 = call i32 @llvm.bswap.i32(i32 %14) + %16 = and i32 65535, %15 + call void (ptr, ...) @printf(ptr @.str, i32 %16) + store [4 x i8] c"\F0\EA\0B\00", ptr %xy, align 1 + store ptr %xy, ptr %abc, align 8 + %17 = load ptr, ptr %abc, align 8 + store ptr %17, ptr %z, align 8 + %18 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 0 + %19 = load i8, ptr %18, align 1 + %20 = zext i8 %19 to i32 + %21 = lshr i32 %20, 4 + %22 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 1 + %23 = load i8, ptr %22, align 1 + %24 = zext i8 %23 to i32 + %25 = shl i32 %24, 4 + %26 = or i32 %25, %21 + %27 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 2 + %28 = load i8, ptr %27, align 1 + %29 = zext i8 %28 to i32 + %30 = shl i32 %29, 12 + %31 = or i32 %30, %26 + %32 = and i32 65535, %31 + call void (ptr, ...) @printf(ptr @.str.1, i32 %32) + %33 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 0 + %34 = load i8, ptr %33, align 1 + %35 = and i8 %34, 15 + %36 = or i8 %35, -16 + store i8 %36, ptr %33, align 1 + %37 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 1 + store i8 -18, ptr %37, align 1 + %38 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 2 + %39 = load i8, ptr %38, align 1 + %40 = and i8 %39, -16 + %41 = or i8 %40, 11 + store i8 %41, ptr %38, align 1 + %42 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 0 + %43 = load i8, ptr %42, align 1 + %44 = zext i8 %43 to i32 + %45 = lshr i32 %44, 4 + %46 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 1 + %47 = load i8, ptr %46, align 1 + %48 = zext i8 %47 to i32 + %49 = shl i32 %48, 4 + %50 = or i32 %49, %45 + %51 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 2 + %52 = load i8, ptr %51, align 1 + %53 = zext i8 %52 to i32 + %54 = shl i32 %53, 12 + %55 = or i32 %54, %50 + %56 = and i32 65535, %55 + call void (ptr, ...) @printf(ptr @.str.2, i32 %56) + %57 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 0 + %58 = load i8, ptr %57, align 1 + %59 = and i8 %58, 15 + %60 = or i8 %59, -32 + store i8 %60, ptr %57, align 1 + %61 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 1 + store i8 -5, ptr %61, align 1 + %62 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 2 + %63 = load i8, ptr %62, align 1 + %64 = and i8 %63, -16 + %65 = or i8 %64, 14 + store i8 %65, ptr %62, align 1 + %66 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 0 + %67 = load i8, ptr %66, align 1 + %68 = zext i8 %67 to i32 + %69 = lshr i32 %68, 4 + %70 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 1 + %71 = load i8, ptr %70, align 1 + %72 = zext i8 %71 to i32 + %73 = shl i32 %72, 4 + %74 = or i32 %73, %69 + %75 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 2 + %76 = load i8, ptr %75, align 1 + %77 = zext i8 %76 to i32 + %78 = shl i32 %77, 12 + %79 = or i32 %78, %74 + %80 = shl i32 %79, 16 + %81 = call i32 @llvm.bswap.i32(i32 %80) + %82 = and i32 65535, %81 + call void (ptr, ...) @printf(ptr @.str.3, i32 %82) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/bitstruct_general.c3 b/test/test_suite2/bitstruct/bitstruct_general.c3 new file mode 100644 index 000000000..62580160b --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_general.c3 @@ -0,0 +1,46 @@ +// #target: macos-x64 + +module foo; + + +bitstruct BitField +{// #error: followed by bitstruct type + int a : 0..2; + int b : 4..6; + int c : 7..8; +} + + +bitstruct BitField2 : char +{ + int a : 0..2; + int b : 4..6; + int c : 7..8; +} + +struct Packet +{ + bitstruct : int + { + int a : 0..2; + int b : 3..5; + int c : 5..6; + } + int packet_id; +} + +bitstruct BitField3 : char[3] +{ + int a : 0..2; + int b : 3..8; + int c : 9..18; + int d : 19..23; +} + +bitstruct BitField4 : char[3] @align(8) +{ + int a : 0..2; + int b : 3..7; + int c : 8..15; + int d : 16..19; +} diff --git a/test/test_suite2/bitstruct/bitstruct_init.c3 b/test/test_suite2/bitstruct/bitstruct_init.c3 new file mode 100644 index 000000000..ebb316d4c --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_init.c3 @@ -0,0 +1,62 @@ +module foo; + +bitstruct Foo : uint +{ + int x : 1..3; + uint y : 11..13; + int z : 15..15; +} + +struct Bar +{ + int x; + bitstruct baz : int + { + int x : 1..3; + } +} + +struct Bar2 +{ + int x; + bitstruct : int + { + int z : 1..3; + } + +} +fn void testNested() +{ + Bar b1 = { 3, { 3 } }; + Bar b2 = { .x = 3, .baz.x = 3 }; + Bar2 b3 = { 1, 3 }; + Bar2 b4 = { .x = 123, .z = 3 }; + Bar2 b5 = { .x = 123, .z = 4 }; // #error: would be truncated + Bar2 b6 = { 1, 4 }; // #error: would be truncated + Bar b7 = { 3, { 4 } }; // #error: would be truncated + Bar b8 = { .x = 3, .baz.x = 4 }; // #error: would be truncated + +} + +fn void test() +{ + Foo abc = {}; + abc.x = -4; + abc.z = 0; + abc.z = -1; + abc.x = 3; + abc.y = 7; + abc.x = -5; // #error: would be truncated + abc.x = 4; // #error: would be truncated + abc.y = 8; // #error: would be truncated +} + +fn void test2() +{ + Foo abc = { -4, 8, 0 }; // #error: would be truncated +} + +fn void test3() +{ + Foo abc = { .x = -4, .z = 0, .y = 8 }; // #error: would be truncated +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/bitstruct_intcontainer.c3t b/test/test_suite2/bitstruct/bitstruct_intcontainer.c3t new file mode 100644 index 000000000..a90313bb1 --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_intcontainer.c3t @@ -0,0 +1,105 @@ +// #target: macos-x64 + +module foo; + +bitstruct BitFieldCross : uint +{ + uint d : 0..4; + int a : 5..22; + uint c : 23..31; +} + +bitstruct BitFieldCrossU : int +{ + uint d : 0..4; + uint a : 5..22; + uint c : 23..31; +} + +bitstruct BitFieldCrossUL : long +{ + uint d : 0..4; + uint a : 5..22; + uint c : 23..40; + uint e : 41..61; +} + +bitstruct BitFieldCrossULBE : long @bigendian +{ + uint d : 0..4; + uint a : 5..22; + uint c : 23..40; + uint e : 41..61; +} +extern fn void printf(char*, ...); + +fn void main() +{ + BitFieldCross xx = { 0, -15, 0 }; + printf("%d\n", xx.a); + xx = { 0x1f, -15, 0x7f }; + printf("%d\n", xx.a); + BitFieldCrossU xxu = { 0x1f, 0x25678, 0x1ff }; + printf("%x\n", xxu.a); + BitFieldCrossUL xxy = { 0x1f, 0x25678, 0xeffe, 0xa9597 }; + printf("%x, %x, %x\n", xxy.a, xxy.c, xxy.e); + BitFieldCrossULBE xxybe = { 0x1f, 0x25678, 0xeffe, 0xa9597 }; + printf("%x, %x, %x\n", xxybe.a, xxybe.c, xxybe.e); +} + + +/* #expect: foo.ll + +entry: + %xx = alloca i32, align 4 + %xxu = alloca i32, align 4 + %xxy = alloca i64, align 8 + %xxybe = alloca i64, align 8 + store i32 8388128, ptr %xx, align 4 + %0 = load i32, ptr %xx, align 4 + %1 = shl i32 %0, 9 + %2 = ashr i32 %1, 14 + call void (ptr, ...) @printf(ptr @.str, i32 %2) + store i32 1073741375, ptr %xx, align 4 + %3 = load i32, ptr %xx, align 4 + %4 = shl i32 %3, 9 + %5 = ashr i32 %4, 14 + call void (ptr, ...) @printf(ptr @.str.1, i32 %5) + store i32 -3485921, ptr %xxu, align 4 + %6 = load i32, ptr %xxu, align 4 + %7 = lshr i32 %6, 5 + %8 = and i32 262143, %7 + call void (ptr, ...) @printf(ptr @.str.2, i32 %8) + store i64 1525363991714123551, ptr %xxy, align 8 + %9 = load i64, ptr %xxy, align 8 + %10 = lshr i64 %9, 5 + %11 = and i64 262143, %10 + %12 = trunc i64 %11 to i32 + %13 = load i64, ptr %xxy, align 8 + %14 = lshr i64 %13, 23 + %15 = and i64 262143, %14 + %16 = trunc i64 %15 to i32 + %17 = load i64, ptr %xxy, align 8 + %18 = lshr i64 %17, 41 + %19 = and i64 2097151, %18 + %20 = trunc i64 %19 to i32 + call void (ptr, ...) @printf(ptr @.str.3, i32 %12, i32 %16, i32 %20) + store i64 2292133196431502101, ptr %xxybe, align 8 + %21 = load i64, ptr %xxybe, align 8 + %22 = call i64 @llvm.bswap.i64(i64 %21) + %23 = lshr i64 %22, 5 + %24 = and i64 262143, %23 + %25 = trunc i64 %24 to i32 + %26 = load i64, ptr %xxybe, align 8 + %27 = call i64 @llvm.bswap.i64(i64 %26) + %28 = lshr i64 %27, 23 + %29 = and i64 262143, %28 + %30 = trunc i64 %29 to i32 + %31 = load i64, ptr %xxybe, align 8 + %32 = call i64 @llvm.bswap.i64(i64 %31) + %33 = lshr i64 %32, 41 + %34 = and i64 2097151, %33 + %35 = trunc i64 %34 to i32 + call void (ptr, ...) @printf(ptr @.str.4, i32 %25, i32 %30, i32 %35) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/bitstruct_overlap.c3 b/test/test_suite2/bitstruct/bitstruct_overlap.c3 new file mode 100644 index 000000000..bbee3b194 --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_overlap.c3 @@ -0,0 +1,47 @@ +bitstruct Foo1 : char +{ + int a : 2..5; + int b : 5..6; // #error: Overlapping members +} + +bitstruct Foo2 : char +{ + int a : 2..5; + int b : 4..6; // #error: Overlapping members +} + +bitstruct Foo3 : char +{ + int a : 2..5; + int b : 2..6; // #error: Overlapping members +} + +bitstruct Foo4 : char +{ + int a : 2..5; + int b : 1..6; // #error: Overlapping members +} + +bitstruct Foo5 : char +{ + int a : 2..5; + int b : 1..3; // #error: Overlapping members +} + +bitstruct Foo6 : char +{ + int a : 2..5; + int b : 1..1; +} + +bitstruct Foo7 : char @overlap +{ + int a : 2..5; + int b : 1..3; +} + +bitstruct Foo8 : char +{ + int a : 2..5; + bool b : 3; // #error: Overlapping members +} diff --git a/test/test_suite2/bitstruct/bitstruct_single_error.c3 b/test/test_suite2/bitstruct/bitstruct_single_error.c3 new file mode 100644 index 000000000..663cf196c --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_single_error.c3 @@ -0,0 +1,19 @@ +bitstruct Foo1 : char +{ + char x : 1..1; +} + +bitstruct Foo2 : char +{ + char x : 1; // #error: Only booleans may use non-range indices +} + +bitstruct Foo3 : char +{ + bool x : 0..2; // #error: The bit width of 'bool' +} + +bitstruct Foo4 : int +{ + char x : 0..15; // #error: The bit width of 'char' +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/bitstruct_to_int.c3t b/test/test_suite2/bitstruct/bitstruct_to_int.c3t new file mode 100644 index 000000000..81c16c9a5 --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_to_int.c3t @@ -0,0 +1,103 @@ +// #target: macos-x64 + +module foo; + +extern fn void printf(char*, ...); + +bitstruct Foo : uint +{ + int x : 1..3; + uint y : 11..13; + int z : 15..15; +} + +bitstruct Foo2 : char[4] +{ + int x : 1..3; + uint y : 11..13; + int z : 15..15; +} + +fn void test() +{ + Foo b = {}; + int x = (int)b; + char[4] y = (char[4])b; + Foo *c = &b; + c.x; + int* x2 = (int*)c; + char[4]* y2 = (char[4]*)c; +} + +fn void test2() +{ + Foo2 b = { 3, 2, -1 }; + int x = (int)b; + char[4] y = (char[4])b; + Foo2 *c = &b; + printf("%d\n", c.x); + int* x2 = (int*)c; + char[4]* y2 = (char[4]*)c; +} + +fn void main() +{ + test(); + test2(); +} + +/* #expect: foo.ll + +define void @foo.test() #0 { +entry: + %b = alloca i32, align 4 + %x = alloca i32, align 4 + %y = alloca [4 x i8], align 1 + %c = alloca ptr, align 8 + %x2 = alloca ptr, align 8 + %y2 = alloca ptr, align 8 + store i32 0, ptr %b, align 4 + %0 = load i32, ptr %b, align 4 + store i32 %0, ptr %x, align 4 + %1 = load [4 x i8], ptr %b, align 4 + store [4 x i8] %1, ptr %y, align 1 + store ptr %b, ptr %c, align 8 + %2 = load ptr, ptr %c, align 8 + %3 = load i32, ptr %2, align 8 + %4 = shl i32 %3, 28 + %5 = ashr i32 %4, 29 + %6 = load ptr, ptr %c, align 8 + store ptr %6, ptr %x2, align 8 + %7 = load ptr, ptr %c, align 8 + store ptr %7, ptr %y2, align 8 + ret void +} + +; Function Attrs: nounwind +define void @foo.test2() #0 { +entry: + %b = alloca [4 x i8], align 1 + %x = alloca i32, align 4 + %y = alloca [4 x i8], align 1 + %c = alloca ptr, align 8 + %x2 = alloca ptr, align 8 + %y2 = alloca ptr, align 8 + store [4 x i8] c"\06\90\00\00", ptr %b, align 1 + %0 = load i32, ptr %b, align 1 + store i32 %0, ptr %x, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 %b, i32 4, i1 false) + store ptr %b, ptr %c, align 8 + %1 = load ptr, ptr %c, align 8 + %2 = getelementptr inbounds [4 x i8], ptr %1, i64 0, i64 0 + %3 = load i8, ptr %2, align 1 + %4 = zext i8 %3 to i32 + %5 = lshr i32 %4, 1 + %6 = shl i32 %5, 29 + %7 = ashr i32 %6, 29 + call void (ptr, ...) @printf(ptr @.str, i32 %7) + %8 = load ptr, ptr %c, align 8 + store ptr %8, ptr %x2, align 8 + %9 = load ptr, ptr %c, align 8 + store ptr %9, ptr %y2, align 8 + ret void +} diff --git a/test/test_suite2/bitstruct/embedded_bitstruct.c3t b/test/test_suite2/bitstruct/embedded_bitstruct.c3t new file mode 100644 index 000000000..5686873dd --- /dev/null +++ b/test/test_suite2/bitstruct/embedded_bitstruct.c3t @@ -0,0 +1,79 @@ +// #target: macos-x64 + +module foo; + +struct Bar +{ + int x; + struct + { + struct + { + int y; + } + } + bitstruct : uint + { + int ww : 2..10; + } +} + +struct Foo +{ + struct + { + struct + { + int x; + } + struct + { + int y; + } + int z; + } + int w; +} +extern fn void printf(char*, ...); + +fn void main() +{ + Bar b = { 1, 2, -5 }; + printf("%d %d\n", b.y, b.ww); + Foo f = { 5, 6, 7, 8 }; + printf("%d %d %d %d\n", f.x, f.y, f.z, f.w); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %b = alloca %Bar, align 4 + %f = alloca %Foo, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 4 @.__const, i32 12, i1 false) + %0 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 1 + %1 = getelementptr inbounds %anon, ptr %0, i32 0, i32 0 + %2 = getelementptr inbounds %anon.0, ptr %1, i32 0, i32 0 + %3 = load i32, ptr %2, align 4 + %4 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 2 + %5 = load i32, ptr %4, align 4 + %6 = shl i32 %5, 21 + %7 = ashr i32 %6, 23 + call void (ptr, ...) @printf(ptr @.str, i32 %3, i32 %7) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %f, ptr align 4 @.__const.5, i32 16, i1 false) + %8 = getelementptr inbounds %Foo, ptr %f, i32 0, i32 0 + %9 = getelementptr inbounds %anon.1, ptr %8, i32 0, i32 0 + %10 = getelementptr inbounds %anon.2, ptr %9, i32 0, i32 0 + %11 = load i32, ptr %10, align 4 + %12 = getelementptr inbounds %Foo, ptr %f, i32 0, i32 0 + %13 = getelementptr inbounds %anon.1, ptr %12, i32 0, i32 1 + %14 = getelementptr inbounds %anon.3, ptr %13, i32 0, i32 0 + %15 = load i32, ptr %14, align 4 + %16 = getelementptr inbounds %Foo, ptr %f, i32 0, i32 0 + %17 = getelementptr inbounds %anon.1, ptr %16, i32 0, i32 2 + %18 = load i32, ptr %17, align 4 + %19 = getelementptr inbounds %Foo, ptr %f, i32 0, i32 1 + %20 = load i32, ptr %19, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %11, i32 %15, i32 %18, i32 %20) + ret void +} diff --git a/test/test_suite2/bitstruct/invalid_bitstruct_member_types.c3 b/test/test_suite2/bitstruct/invalid_bitstruct_member_types.c3 new file mode 100644 index 000000000..21a1aaa19 --- /dev/null +++ b/test/test_suite2/bitstruct/invalid_bitstruct_member_types.c3 @@ -0,0 +1,26 @@ + +bitstruct Test : int +{ + bool x : 0..0; + float a : 1..3; // #error: 'float' is not supported in a bitstruct, only enums, integer and boolean values may be used. +} + +define Baz = distinct float; +define Foo = distinct bool; +enum Boo +{ + BAR +} +bitstruct Test2 : int +{ + Foo x : 0..0; + Boo y : 4..6; + Baz a : 1..3; // #error: 'Baz' is not supported in a bitstruct, only enums, integer and boolean values may be used. +} + + +bitstruct Test3 : int +{ + Foo x : 0..0; + Brob a : 1..3; // #error: 'Brob' could not be found, did you spell it right? +} diff --git a/test/test_suite2/bitstruct/invalid_bitstruct_name_other_ident.c3 b/test/test_suite2/bitstruct/invalid_bitstruct_name_other_ident.c3 new file mode 100644 index 000000000..29aee7ed2 --- /dev/null +++ b/test/test_suite2/bitstruct/invalid_bitstruct_name_other_ident.c3 @@ -0,0 +1,20 @@ +bitstruct test : int // #error: Names of bitstructs must start with an upper case letter. +{ + int a : 1..3; + int b : 5..10; + uint c : 20..20; +} + +bitstruct $if : int // #error: 'bitstruct' should be followed by the name of the bitstruct. +{ + int a : 1..3; + int b : 5..10; + uint c : 20..20; +} + +bitstruct if : int // #error: Names of bitstructs must start with an upper case letter. +{ + int a : 1..3; + int b : 5..10; + uint c : 20..20; +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/invalid_bitstruct_type.c3 b/test/test_suite2/bitstruct/invalid_bitstruct_type.c3 new file mode 100644 index 000000000..d4d616ec0 --- /dev/null +++ b/test/test_suite2/bitstruct/invalid_bitstruct_type.c3 @@ -0,0 +1,7 @@ + +bitstruct Test : float // #error: The type of the bitstruct cannot be 'float' but must be an integer or an array of integers. +{ + int a : 1..3; + int b : 5..10; + uint c : 20..20; +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/invalid_empty_struct_union.c3 b/test/test_suite2/bitstruct/invalid_empty_struct_union.c3 new file mode 100644 index 000000000..d51661a07 --- /dev/null +++ b/test/test_suite2/bitstruct/invalid_empty_struct_union.c3 @@ -0,0 +1,7 @@ +struct Foo // #error: Zero sized structs are not permitted. +{ +} + +union Bar // #error: Zero sized unions are not permitted. +{ +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/missing_bitstruct_type.c3 b/test/test_suite2/bitstruct/missing_bitstruct_type.c3 new file mode 100644 index 000000000..1b82e0c70 --- /dev/null +++ b/test/test_suite2/bitstruct/missing_bitstruct_type.c3 @@ -0,0 +1,3 @@ +bitstruct BitField +{ // #error: followed by bitstruct +} \ No newline at end of file diff --git a/test/test_suite2/builtins/simple_builtins.c3t b/test/test_suite2/builtins/simple_builtins.c3t new file mode 100644 index 000000000..d18f6dcc0 --- /dev/null +++ b/test/test_suite2/builtins/simple_builtins.c3t @@ -0,0 +1,57 @@ +// #target: macos-x64 +module foo; + +fn int foo(double b) +{ + double d = $$ceil(b); + double e = $$max(1.0, d); + double f = $$fma(d, 2.0, 3.0); + int xeb = 13; + + int[3] abcd; + int sy = $$volatile_load(&xeb); + $$volatile_store(&xeb, sy + 1); + $$volatile_store(&abcd[2], sy + 2); + sy = $$volatile_load(&abcd[2]); + return 1; +} + +/* #expect: foo.ll + +define i32 @foo.foo(double %0) #0 { +entry: + %d = alloca double, align 8 + %e = alloca double, align 8 + %f = alloca double, align 8 + %xeb = alloca i32, align 4 + %abcd = alloca [3 x i32], align 4 + %sy = alloca i32, align 4 + %1 = call double @llvm.ceil.f64(double %0) + store double %1, ptr %d, align 8 + %2 = load double, ptr %d, align 8 + %3 = call double @llvm.maxnum.f64(double 1.000000e+00, double %2) + store double %3, ptr %e, align 8 + %4 = load double, ptr %d, align 8 + %5 = call double @llvm.fma.f64(double %4, double 2.000000e+00, double 3.000000e+00) + store double %5, ptr %f, align 8 + store i32 13, ptr %xeb, align 4 + %6 = getelementptr inbounds [3 x i32], ptr %abcd, i64 0, i64 0 + store i32 0, ptr %6, align 4 + %7 = getelementptr inbounds [3 x i32], ptr %abcd, i64 0, i64 1 + store i32 0, ptr %7, align 4 + %8 = getelementptr inbounds [3 x i32], ptr %abcd, i64 0, i64 2 + store i32 0, ptr %8, align 4 + %9 = load volatile i32, ptr %xeb, align 4 + store i32 %9, ptr %sy, align 4 + %10 = load i32, ptr %sy, align 4 + %add = add i32 %10, 1 + store volatile i32 %add, ptr %xeb, align 4 + %11 = getelementptr inbounds [3 x i32], ptr %abcd, i64 0, i64 2 + %12 = load i32, ptr %sy, align 4 + %add1 = add i32 %12, 2 + store volatile i32 %add1, ptr %11, align 4 + %13 = getelementptr inbounds [3 x i32], ptr %abcd, i64 0, i64 2 + %14 = load volatile i32, ptr %13, align 4 + store i32 %14, ptr %sy, align 4 + ret i32 1 +} diff --git a/test/test_suite2/cast/cast_from_ptr.c3t b/test/test_suite2/cast/cast_from_ptr.c3t new file mode 100644 index 000000000..523ea2c60 --- /dev/null +++ b/test/test_suite2/cast/cast_from_ptr.c3t @@ -0,0 +1,22 @@ +module test; + +fn void tester() +{ + int *x; + short y = (short)((uptr)(x)); + uptr z = (uptr)((short)((uptr)(x))); +} + +/* #expect: test.ll + + %x = alloca ptr, align 8 + %y = alloca i16, align 2 + %z = alloca i64, align 8 + store ptr null, ptr %x, align 8 + %0 = load ptr, ptr %x, align 8 + %ptrxi = ptrtoint ptr %0 to i16 + store i16 %ptrxi, ptr %y, align 2 + %1 = load ptr, ptr %x, align 8 + %ptrxi1 = ptrtoint ptr %1 to i16 + %siuiext = sext i16 %ptrxi1 to i64 + store i64 %siuiext, ptr %z, align 8 diff --git a/test/test_suite2/cast/cast_ok.c3 b/test/test_suite2/cast/cast_ok.c3 new file mode 100644 index 000000000..8ce12894c --- /dev/null +++ b/test/test_suite2/cast/cast_ok.c3 @@ -0,0 +1,11 @@ +struct Foo { int a; } + +fn void test4() +{ + int x = (int)(32); +} + +fn void test5() +{ + Foo x = (Foo)(Foo{32}); +} \ No newline at end of file diff --git a/test/test_suite2/cast/cast_parse_fails.c3 b/test/test_suite2/cast/cast_parse_fails.c3 new file mode 100644 index 000000000..e52fbad02 --- /dev/null +++ b/test/test_suite2/cast/cast_parse_fails.c3 @@ -0,0 +1,13 @@ +struct Foo { int a; } + +fn void test2() +{ + int x = int{ 32 }; // #error: 'int' cannot use compound literal initialization, did you intend to use a cast +} + +fn void test3() +{ + int x = int(32); // #error: A type cannot be followed by (), if you intended a cast, use (type)(expression) +} + + diff --git a/test/test_suite2/cast/cast_parse_fails2.c3 b/test/test_suite2/cast/cast_parse_fails2.c3 new file mode 100644 index 000000000..488b9e25e --- /dev/null +++ b/test/test_suite2/cast/cast_parse_fails2.c3 @@ -0,0 +1,8 @@ + +struct Foo { int a; } + +fn void test1() +{ + Foo({ 32 }); // #error: A type cannot be followed by (), if you intended a cast, use (type)(expression) + (Foo)({ 32 }); // #error: Casting from an untyped list to a concrete type is not possible. +} \ No newline at end of file diff --git a/test/test_suite2/cast/cast_struct.c3 b/test/test_suite2/cast/cast_struct.c3 new file mode 100644 index 000000000..d3a4addfc --- /dev/null +++ b/test/test_suite2/cast/cast_struct.c3 @@ -0,0 +1,37 @@ +struct Foo +{ + int a; + float b; +} + +struct Bar +{ + int b; + float c; +} + +struct Baz +{ + int b; + int c; +} + +struct BazTwo +{ + int[1] d; + int e; +} + +fn void test() +{ + Foo x; + Bar y = (Bar)(x); + + Baz z; + int[2] w = (int[2])(z); + z = (Baz)(w); + BazTwo v = (BazTwo)(z); + v = (BazTwo)(w); + z = (Baz)(v); + w = (int[2])(v); +} diff --git a/test/test_suite2/cast/cast_struct_fails.c3 b/test/test_suite2/cast/cast_struct_fails.c3 new file mode 100644 index 000000000..244ae1cfc --- /dev/null +++ b/test/test_suite2/cast/cast_struct_fails.c3 @@ -0,0 +1,35 @@ +struct Foo +{ + int a; + float b; +} + +struct Bar +{ + int b; + float c; +} + +struct Baz +{ + int b; + int c; +} + +struct BazTwo +{ + int[2] d; + int e; +} + +fn void test1() +{ + Foo x; + Bar z = (Baz)(x); // #error: cast 'Foo' to 'Baz' +} +fn void test2() +{ + Baz x; + BazTwo z = (BazTwo)(x); // #error: cast 'Baz' to 'BazTwo' +} + diff --git a/test/test_suite2/cast/cast_to_failable.c3 b/test/test_suite2/cast/cast_to_failable.c3 new file mode 100644 index 000000000..e47ee8206 --- /dev/null +++ b/test/test_suite2/cast/cast_to_failable.c3 @@ -0,0 +1,12 @@ +fault MyErr +{ + FOO +} + +fn void test() +{ + int! x; + int! d = ($typeof(MyErr.FOO!))(x); // #error: Casting to a failable type is not allowed +} + + diff --git a/test/test_suite2/cast/top_down_cast_fails.c3 b/test/test_suite2/cast/top_down_cast_fails.c3 new file mode 100644 index 000000000..092c9cbf5 --- /dev/null +++ b/test/test_suite2/cast/top_down_cast_fails.c3 @@ -0,0 +1,29 @@ +fn void test() +{ + int x; + int y; + long z = x * y; + z = x * y + z; // #error: 'int' to 'long' + z = x * y + x; // #error: 'int' to 'long' + z = x / y; + z = x + y; + z = x - y; + z = x % y; + z = x / y + z; // #error: 'int' to 'long' + z = x + y + z; // #error: 'int' to 'long' + z = x - y + z; // #error: 'int' to 'long' + z = x % y + z; // #error: 'int' to 'long' + z = x / y + x; // #error: 'int' to 'long' + z = x + y + x; // #error: 'int' to 'long' + z = x - y + x; // #error: 'int' to 'long' + z = x % y + x; // #error: 'int' to 'long' + + z = x << y + x; // #error: 'int' to 'long' + z = x >> y + x; // #error: 'int' to 'long' + z = x << y + z; // #error: 'int' to 'long' + z = x >> y + z; // #error: 'int' to 'long' + z = ~x + x; // #error: 'int' to 'long' + z = ~x + z; // #error: 'int' to 'long' + z = -x + z; // #error: 'int' to 'long' + z = x + z; +} \ No newline at end of file diff --git a/test/test_suite2/cast/top_down_casts.c3t b/test/test_suite2/cast/top_down_casts.c3t new file mode 100644 index 000000000..83038bedd --- /dev/null +++ b/test/test_suite2/cast/top_down_casts.c3t @@ -0,0 +1,101 @@ +fn void test() +{ + int x; + int y; + long z = x * y; + z = x / y; + z = x + y; + z = x - y; + z = x % y; + z = x << y; + z = x >> y; + z = ~x; + z = -x; + int! w; + z = w ?? 1; +} + +// #expect: top_down_casts.ll + +define void @top_down_casts.test() #0 { +entry: + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %z = alloca i64, align 8 + %w = alloca i32, align 4 + %w.f = alloca i64, align 8 + store i32 0, ptr %x, align 4 + store i32 0, ptr %y, align 4 + %0 = load i32, ptr %x, align 4 + %sisiext = sext i32 %0 to i64 + %1 = load i32, ptr %y, align 4 + %sisiext1 = sext i32 %1 to i64 + %mul = mul i64 %sisiext, %sisiext1 + store i64 %mul, ptr %z, align 8 + %2 = load i32, ptr %x, align 4 + %sisiext2 = sext i32 %2 to i64 + %3 = load i32, ptr %y, align 4 + %sisiext3 = sext i32 %3 to i64 + %sdiv = sdiv i64 %sisiext2, %sisiext3 + store i64 %sdiv, ptr %z, align 8 + %4 = load i32, ptr %x, align 4 + %sisiext4 = sext i32 %4 to i64 + %5 = load i32, ptr %y, align 4 + %sisiext5 = sext i32 %5 to i64 + %add = add i64 %sisiext4, %sisiext5 + store i64 %add, ptr %z, align 8 + %6 = load i32, ptr %x, align 4 + %sisiext6 = sext i32 %6 to i64 + %7 = load i32, ptr %y, align 4 + %sisiext7 = sext i32 %7 to i64 + %sub = sub i64 %sisiext6, %sisiext7 + store i64 %sub, ptr %z, align 8 + %8 = load i32, ptr %x, align 4 + %sisiext8 = sext i32 %8 to i64 + %9 = load i32, ptr %y, align 4 + %sisiext9 = sext i32 %9 to i64 + %smod = srem i64 %sisiext8, %sisiext9 + store i64 %smod, ptr %z, align 8 + %10 = load i32, ptr %x, align 4 + %sisiext10 = sext i32 %10 to i64 + %11 = load i32, ptr %y, align 4 + %12 = zext i32 %11 to i64 + %shl = shl i64 %sisiext10, %12 + %13 = freeze i64 %shl + store i64 %13, ptr %z, align 8 + %14 = load i32, ptr %x, align 4 + %sisiext11 = sext i32 %14 to i64 + %15 = load i32, ptr %y, align 4 + %16 = zext i32 %15 to i64 + %ashr = ashr i64 %sisiext11, %16 + %17 = freeze i64 %ashr + store i64 %17, ptr %z, align 8 + %18 = load i32, ptr %x, align 4 + %sisiext12 = sext i32 %18 to i64 + %bnot = xor i64 %sisiext12, -1 + store i64 %bnot, ptr %z, align 8 + %19 = load i32, ptr %x, align 4 + %sisiext13 = sext i32 %19 to i64 + %20 = load i32, ptr %x, align 4 + %sisiext14 = sext i32 %20 to i64 + %neg = sub i64 0, %sisiext14 + store i64 %neg, ptr %z, align 8 + store i64 0, ptr %w.f, align 8 + store i32 0, ptr %w, align 4 + %21 = load i64, ptr %w.f, align 8 + %not_err = icmp eq i64 %21, 0 + br i1 %not_err, label %after_check, label %else_block + +after_check: ; preds = %entry + %22 = load i32, ptr %w, align 4 + %sisiext15 = sext i32 %22 to i64 + br label %phi_block + +else_block: ; preds = %entry + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val = phi i64 [ %sisiext15, %after_check ], [ 1, %else_block ] + store i64 %val, ptr %z, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/clang/2002-01_02.c3t b/test/test_suite2/clang/2002-01_02.c3t new file mode 100644 index 000000000..fe71a3095 --- /dev/null +++ b/test/test_suite2/clang/2002-01_02.c3t @@ -0,0 +1,346 @@ +// #target: macos-x64 +module test; + +struct Foo { int x, y; } +Foo[10] array; + +fn void foo() {} + +fn void *dlclose(void*); + +fn void ap_os_dso_unload(void *handle) +{ + dlclose(handle); + return; +} + +extern fn void foo2(int, double, float); + +fn void bar(int x) { + foo2(x, x ? 1.0 : 12.5, 1.0f); +} + +extern fn int tolower(int); + +fn char *rangematch(char *pattern, int teste, int c) { + + if ((c <= teste) | (tolower(c) <= tolower((char)(teste)))) return (char*)(0); + + return pattern; +} + +struct Foostruct { + short x; +} + +extern fn int foo3(Foostruct ic); + +fn void teste2() { + Foostruct xqic; + foo3(xqic); +} + +struct Vertex +{ + float a, b, c; +} +struct Edge_rec +{ + Vertex *v; + Edge_rec *next; + int wasseen; + int more_data; +} + +define QuadEdge = Edge_rec*; + +struct EdgePair { + QuadEdge left, right; +} + +struct EdgeStack { + int ptr; + QuadEdge *elts; + int stack_size; +} + +fn int do_merge(QuadEdge ldo, QuadEdge rdo) { + int lvalid; + QuadEdge basel; + QuadEdge rcand; + while (1) { + if (!lvalid) { + return (int)((iptr)(basel.next)); + } + } + return 1; +} + +fn int test(int x) { + return x; +} + +fn void abc(int *x); +fn int def(int y, int z) { + abc(&z); + return y; +} + +struct Test { short x, x2; int y, z; } + +fn int testing(Test *a) { + return a.x2+a.y; +} + +fn int test2(int x, Test a, int y) { + return x+y+a.x2+a.y; +} +fn int test3(Test a, Test b) { + return a.x2+a.y+b.y+b.z; +} + +fn Test test4(Test a) { + return a; +} + +fn int test6() { + int[200] b; + return b[4]; +} + +struct STest2 { int x; short[4] y; double z; } + +fn STest2 test7(STest2 x) { + return x; +} + +extern fn int printf(char * format, ...); + +fn int main2() { + long v = 123455678902i64; + printf("%lld\n", v); + return 1; +} + +double afoo = 17; +double abar = 12.0; +float axx = 12.0f; + +char*[*] procnames = { + "EXIT" +}; + +void *[*] data = { &afoo, &abar, &axx }; + +/* #expect: test.ll + +%Foo = type { i32, i32 } +%Foostruct = type { i16 } +%Edge_rec = type { ptr, ptr, i32, i32 } +%Test = type { i16, i16, i32, i32 } +%STest2 = type { i32, [4 x i16], double } + +@test.array = local_unnamed_addr global [10 x %Foo] zeroinitializer, align 16 +@test.afoo = global double 1.700000e+01, align 8 +@test.abar = global double 1.200000e+01, align 8 +@test.axx = global float 1.200000e+01, align 4 +@.str = private unnamed_addr constant [5 x i8] c"EXIT\00", align 1 +@test.procnames = local_unnamed_addr global [1 x ptr] [ptr @.str], align 8 +@test.data = local_unnamed_addr global [3 x ptr] [ptr @test.afoo, ptr @test.abar, ptr @test.axx], align 16 +@.str.6 = private unnamed_addr constant [6 x i8] c"%lld\0A\00", align 1 + +define void @test.foo() #0 { +entry: + ret void +} + +declare ptr @test.dlclose(ptr) #0 + +define void @test.ap_os_dso_unload(ptr %0) #0 { +entry: + %1 = call ptr @test.dlclose(ptr %0) + ret void +} + +declare void @foo2(i32, double, float) #0 + +define void @test.bar(i32 %0) #0 { +entry: + %intbool = icmp ne i32 %0, 0 + %ternary = select i1 %intbool, double 1.000000e+00, double 1.250000e+01 + call void @foo2(i32 %0, double %ternary, float 1.000000e+00) + ret void +} + +declare i32 @tolower(i32) #0 + +define ptr @test.rangematch(ptr %0, i32 %1, i32 %2) #0 { +entry: + %le = icmp sle i32 %2, %1 + %3 = call i32 @tolower(i32 %2) + %siuitrunc = trunc i32 %1 to i8 + %uisiext = zext i8 %siuitrunc to i32 + %4 = call i32 @tolower(i32 %uisiext) + %le1 = icmp sle i32 %3, %4 + %or = or i1 %le, %le1 + br i1 %or, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret ptr null + +if.exit: ; preds = %entry + ret ptr %0 +} + +declare i32 @foo3(i16) #0 + +define void @test.teste2() #0 { +entry: + %xqic = alloca %Foostruct, align 2 + store i16 0, ptr %xqic, align 2 + %0 = getelementptr inbounds %Foostruct, ptr %xqic, i32 0, i32 0 + %1 = load i16, ptr %0, align 2 + %2 = call i32 @foo3(i16 %1) + ret void +} + +define i32 @test.do_merge(ptr %0, ptr %1) #0 { +entry: + %lvalid = alloca i32, align 4 + %basel = alloca ptr, align 8 + %rcand = alloca ptr, align 8 + store i32 0, ptr %lvalid, align 4 + store ptr null, ptr %basel, align 8 + store ptr null, ptr %rcand, align 8 + br label %loop.body + +loop.body: ; preds = %if.exit, %entry + %2 = load i32, ptr %lvalid, align 4 + %not = icmp eq i32 %2, 0 + br i1 %not, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + %3 = load ptr, ptr %basel, align 8 + %4 = getelementptr inbounds %Edge_rec, ptr %3, i32 0, i32 1 + %5 = load ptr, ptr %4, align 8 + %ptrxi = ptrtoint ptr %5 to i32 + ret i32 %ptrxi + +if.exit: ; preds = %loop.body + br label %loop.body + +loop.exit: ; No predecessors! + ret i32 1 +} + +define i32 @test.test(i32 %0) #0 { +entry: + ret i32 %0 +} + +declare void @test.abc(ptr) #0 + +define i32 @test.def(i32 %0, i32 %1) #0 { +entry: + %z = alloca i32, align 4 + store i32 %1, ptr %z, align 4 + call void @test.abc(ptr %z) + ret i32 %0 +} + +define i32 @test.testing(ptr %0) #0 { +entry: + %1 = getelementptr inbounds %Test, ptr %0, i32 0, i32 1 + %2 = load i16, ptr %1, align 2 + %sisiext = sext i16 %2 to i32 + %3 = getelementptr inbounds %Test, ptr %0, i32 0, i32 2 + %4 = load i32, ptr %3, align 4 + %add = add i32 %sisiext, %4 + ret i32 %add +} + +define i32 @test.test2(i32 %0, i64 %1, i32 %2, i32 %3) #0 { +entry: + %4 = alloca { i64, i32 }, align 8 + %5 = getelementptr inbounds { i64, i32 }, ptr %4, i32 0, i32 0 + store i64 %1, ptr %5, align 8 + %6 = getelementptr inbounds { i64, i32 }, ptr %4, i32 0, i32 1 + store i32 %2, ptr %6, align 8 + %add = add i32 %0, %3 + %7 = getelementptr inbounds %Test, ptr %4, i32 0, i32 1 + %8 = load i16, ptr %7, align 2 + %sisiext = sext i16 %8 to i32 + %add1 = add i32 %add, %sisiext + %9 = getelementptr inbounds %Test, ptr %4, i32 0, i32 2 + %10 = load i32, ptr %9, align 4 + %add2 = add i32 %add1, %10 + ret i32 %add2 +} + +define i32 @test.test3(i64 %0, i32 %1, i64 %2, i32 %3) #0 { +entry: + %4 = alloca { i64, i32 }, align 8 + %5 = alloca { i64, i32 }, align 8 + %6 = getelementptr inbounds { i64, i32 }, ptr %4, i32 0, i32 0 + store i64 %0, ptr %6, align 8 + %7 = getelementptr inbounds { i64, i32 }, ptr %4, i32 0, i32 1 + store i32 %1, ptr %7, align 8 + %8 = getelementptr inbounds { i64, i32 }, ptr %5, i32 0, i32 0 + store i64 %2, ptr %8, align 8 + %9 = getelementptr inbounds { i64, i32 }, ptr %5, i32 0, i32 1 + store i32 %3, ptr %9, align 8 + %10 = getelementptr inbounds %Test, ptr %4, i32 0, i32 1 + %11 = load i16, ptr %10, align 2 + %sisiext = sext i16 %11 to i32 + %12 = getelementptr inbounds %Test, ptr %4, i32 0, i32 2 + %13 = load i32, ptr %12, align 4 + %add = add i32 %sisiext, %13 + %14 = getelementptr inbounds %Test, ptr %5, i32 0, i32 2 + %15 = load i32, ptr %14, align 4 + %add1 = add i32 %add, %15 + %16 = getelementptr inbounds %Test, ptr %5, i32 0, i32 3 + %17 = load i32, ptr %16, align 8 + %add2 = add i32 %add1, %17 + ret i32 %add2 +} + +define { i64, i32 } @test.test4(i64 %0, i32 %1) #0 { +entry: + %2 = alloca { i64, i32 }, align 8 + %tempcoerce = alloca { i64, i32 }, align 8 + %3 = getelementptr inbounds { i64, i32 }, ptr %2, i32 0, i32 0 + store i64 %0, ptr %3, align 8 + %4 = getelementptr inbounds { i64, i32 }, ptr %2, i32 0, i32 1 + store i32 %1, ptr %4, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %2, i32 12, i1 false) + %5 = load { i64, i32 }, ptr %tempcoerce, align 8 + ret { i64, i32 } %5 +} + +define i32 @test.test6() #0 { +entry: + %b = alloca [200 x i32], align 16 + call void @llvm.memset.p0.i64(ptr align 16 %b, i8 0, i64 800, i1 false) + %0 = getelementptr inbounds [200 x i32], ptr %b, i64 0, i64 4 + %1 = load i32, ptr %0, align 4 + ret i32 %1 +} + +define void @test.test7(ptr noalias sret(%STest2) align 8 %0, ptr byval(%STest2) align 8 %1) #0 { +entry: + %x = alloca %STest2, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x, ptr align 8 %1, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %x, i32 24, i1 false) + ret void +} + +declare i32 @printf(ptr, ...) #0 + +define i32 @test.main2() #0 { +entry: + %v = alloca i64, align 8 + store i64 123455678902, ptr %v, align 8 + %0 = load i64, ptr %v, align 8 + %1 = call i32 (ptr, ...) @printf(ptr @.str.6, i64 %0) + ret i32 1 +} diff --git a/test/test_suite2/clang/2002-03.c3t b/test/test_suite2/clang/2002-03.c3t new file mode 100644 index 000000000..3bb280f67 --- /dev/null +++ b/test/test_suite2/clang/2002-03.c3t @@ -0,0 +1,98 @@ +// #target: macos-x64 +module test; +fn int strcmp(char *s1, char *s2); + +fn int test(char *x) { + /* LLVM-GCC used to emit: + %.LC0 = internal global [3 x sbyte] c"\1F\FFFFFF8B\00" + */ + return strcmp(x, "\x1f\x8B"); +} + +int[10] a = { [0] = 0, [1] = 2 }; + +char[10] str = "x"; + +void*[5] arr = { [0] = null, [1] = null }; + +float[12] f = { [0] = 1.23f, [1] = 34.7f }; + +struct Test { int x; double y; } + +Test[10] array = { [0] = { 2, 12.0 }, [1] = { 3, 24.0 } }; + +int[4][4] b = { [0] = { 1, 2, 3, 4}, [1] = { [0] = 5, [1] = 6, [2] = 7 }, [2] = { [0] = 8, [1] = 9 } }; + +struct Connection { + long to; + char[10] type; + long length; +} + +Connection[3] link += { {1, "link1", 10}, + {2, "link2", 20}, + {3, "link3", 30} }; + + +fn int trys(char *s, int x) +{ + int asa; + double val; + int lLS; + if (x) { + asa = lLS + asa; + } else { + } + return asa+(int)(val); +} + +fn char* foo() { + return "*** Word \"%s\" on line %d is not"; +} + +/* #expect: test.ll + +@test.a = local_unnamed_addr global { i32, i32, [8 x i32] } { i32 0, i32 2, [8 x i32] zeroinitializer }, align 16 +@test.str = local_unnamed_addr global [10 x i8] c"x\00\00\00\00\00\00\00\00\00", align 1 +@test.arr = local_unnamed_addr global { ptr, ptr, [3 x ptr] } zeroinitializer, align 16 +@test.f = local_unnamed_addr global { float, float, [10 x float] } { float 0x3FF3AE1480000000, float 0x40415999A0000000, [10 x float] zeroinitializer }, align 16 +@test.array = local_unnamed_addr global { %Test, %Test, [8 x %Test] } { %Test { i32 2, double 1.200000e+01 }, %Test { i32 3, double 2.400000e+01 }, [8 x %Test] zeroinitializer }, align 16 +@test.b = local_unnamed_addr global { [4 x i32], { i32, i32, i32, i32 }, { i32, i32, [2 x i32] }, [4 x i32] } { [4 x i32] [i32 1, i32 2, i32 3, i32 4], { i32, i32, i32, i32 } { i32 5, i32 6, i32 7, i32 0 }, { i32, i32, [2 x i32] } { i32 8, i32 9, [2 x i32] zeroinitializer }, [4 x i32] zeroinitializer }, align 16 +@test.link = local_unnamed_addr global [3 x %Connection] [%Connection { i64 1, [10 x i8] c"link1\00\00\00\00\00", i64 10 }, %Connection { i64 2, [10 x i8] c"link2\00\00\00\00\00", i64 20 }, %Connection { i64 3, [10 x i8] c"link3\00\00\00\00\00", i64 30 }], align 16 +@.str = private unnamed_addr constant [4 x i8] c"\1F\C2\8B\00", align 1 +@.str.7 = private unnamed_addr constant [32 x i8] c"*** Word \22%s\22 on line %d is not\00", align 1 + +declare i32 @test.strcmp(ptr, ptr) #0 + +define i32 @test.test(ptr %0) #0 { +entry: + %1 = call i32 @test.strcmp(ptr %0, ptr @.str) + ret i32 %1 +} + +define i32 @test.trys(ptr %0, i32 %1) #0 { +entry: + %asa = alloca i32, align 4 + %val = alloca double, align 8 + %lLS = alloca i32, align 4 + store i32 0, ptr %asa, align 4 + store double 0.000000e+00, ptr %val, align 8 + store i32 0, ptr %lLS, align 4 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %if.then, label %if.exit + +if.then: ; preds = %entry + %2 = load i32, ptr %lLS, align 4 + %3 = load i32, ptr %asa, align 4 + %add = add i32 %2, %3 + store i32 %add, ptr %asa, align 4 + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %4 = load i32, ptr %asa, align 4 + %5 = load double, ptr %val, align 8 + %fpsi = fptosi double %5 to i32 + %add1 = add i32 %4, %fpsi + ret i32 %add1 +} diff --git a/test/test_suite2/clang/2002-04.c3t b/test/test_suite2/clang/2002-04.c3t new file mode 100644 index 000000000..2731cae66 --- /dev/null +++ b/test/test_suite2/clang/2002-04.c3t @@ -0,0 +1,166 @@ +// #target: macos-x64 +module test; +extern fn int printf(char *, ...); +extern fn int foo(); + +fn int main2() { + while (foo()) { + switch (foo()) { + case 0: + case 1: + case 2: + case 3: + printf("3"); + nextcase; + case 4: printf("4"); nextcase; + case 5: + case 6: + default: + } + } + return 0; +} + +fn double test(uint x) +{ + double[30] student_t={0.0 , 12.706 , 4.303 , 3.182 , 2.776 , 2.571 , + 2.447 , 2.365 , 2.306 , 2.262 , 2.228 , + 2.201 , 2.179 , 2.160 , 2.145 , 2.131 , + 2.120 , 2.110 , 2.101 , 2.093 , 2.086 , + 2.080 , 2.074 , 2.069 , 2.064 , 2.060 , + 2.056 , 2.052 , 2.048 , 2.045 }; + return student_t[x]; +} + +struct St { + int i; + short s1, s2; +} + +extern fn St func_returning_struct(); + +fn void loop(void) { + func_returning_struct(); +} + +struct FooSt { + char p; + short q; + char r; + int x; + short y, z; + int q2; +} + +extern fn int testF(FooSt x, float); +extern fn int testE(char,short,char,int,int,float); +fn void test3(FooSt *x) { + x.q = 1; +} + +fn void test2(FooSt y) { + testE(y.p, y.q, y.r, y.x, y.y, 0.1f); + testF(y, 0.1f); + test2(y); + test3(&y); +} + +/* #expect: test.ll + + +define i32 @test.main2() #0 { +entry: + %switch = alloca i32, align 4 + br label %loop.cond + +loop.cond: ; preds = %switch.exit, %entry + %0 = call i32 @foo() + %intbool = icmp ne i32 %0, 0 + br i1 %intbool, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = call i32 @foo() + store i32 %1, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %loop.body + %2 = load i32, ptr %switch, align 4 + switch i32 %2, label %switch.exit [ + i32 0, label %switch.case + i32 1, label %switch.case + i32 2, label %switch.case + i32 3, label %switch.case + i32 4, label %switch.case1 + i32 5, label %switch.exit + i32 6, label %switch.exit + ] + +switch.case: ; preds = %switch.entry, %switch.entry, %switch.entry, %switch.entry + %3 = call i32 (ptr, ...) @printf(ptr @.str) + br label %switch.case1 + +switch.case1: ; preds = %switch.entry, %switch.case + %4 = call i32 (ptr, ...) @printf(ptr @.str.1) + br label %switch.exit + +switch.exit: ; preds = %switch.entry, %switch.entry, %switch.case1, %switch.entry + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i32 0 +} + +define double @test.test(i32 %0) #0 { +entry: + %student_t = alloca [30 x double], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %student_t, ptr align 16 @.__const, i32 240, i1 false) + %uiuiext = zext i32 %0 to i64 + %1 = getelementptr inbounds [30 x double], ptr %student_t, i64 0, i64 %uiuiext + %2 = load double, ptr %1, align 8 + ret double %2 +} + +define void @test.loop() #0 { +entry: + %result = alloca %St, align 4 + %0 = call i64 @func_returning_struct() + store i64 %0, ptr %result, align 4 + ret void +} + +declare i32 @testF(ptr byval(%FooSt) align 8, float) #0 + +declare i32 @testE(i8 zeroext, i16 signext, i8 zeroext, i32, i32, float) #0 + +define void @test.test3(ptr %0) #0 { +entry: + %1 = getelementptr inbounds %FooSt, ptr %0, i32 0, i32 1 + store i16 1, ptr %1, align 2 + ret void +} + +define void @test.test2(ptr byval(%FooSt) align 8 %0) #0 { +entry: + %y = alloca %FooSt, align 4 + %indirectarg = alloca %FooSt, align 8 + %indirectarg1 = alloca %FooSt, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 8 %0, i32 20, i1 false) + %1 = getelementptr inbounds %FooSt, ptr %y, i32 0, i32 0 + %2 = load i8, ptr %1, align 4 + %3 = getelementptr inbounds %FooSt, ptr %y, i32 0, i32 1 + %4 = load i16, ptr %3, align 2 + %5 = getelementptr inbounds %FooSt, ptr %y, i32 0, i32 2 + %6 = load i8, ptr %5, align 4 + %7 = getelementptr inbounds %FooSt, ptr %y, i32 0, i32 3 + %8 = load i32, ptr %7, align 4 + %9 = getelementptr inbounds %FooSt, ptr %y, i32 0, i32 4 + %10 = load i16, ptr %9, align 4 + %sisiext = sext i16 %10 to i32 + %11 = call i32 @testE(i8 %2, i16 %4, i8 %6, i32 %8, i32 %sisiext, float 0x3FB99999A0000000) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 4 %y, i32 20, i1 false) + %12 = call i32 @testF(ptr byval(%FooSt) align 8 %indirectarg, float 0x3FB99999A0000000) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg1, ptr align 4 %y, i32 20, i1 false) + call void @test.test2(ptr byval(%FooSt) align 8 %indirectarg1) + call void @test.test3(ptr %y) + ret void +} diff --git a/test/test_suite2/comments/simple_comments.c3 b/test/test_suite2/comments/simple_comments.c3 new file mode 100644 index 000000000..ded9afc18 --- /dev/null +++ b/test/test_suite2/comments/simple_comments.c3 @@ -0,0 +1,15 @@ +module comments; +/* Span *//* style */ + +/* Nested /* Errors // Inside */ */ +// Single line +/* + Multiline span style + */ + +fn void test() +{ + return; +} + +/* /* nested /* comments! */ !! */ goes here */ diff --git a/test/test_suite2/compile_time/compile_time_array.c3t b/test/test_suite2/compile_time/compile_time_array.c3t new file mode 100644 index 000000000..c108d0651 --- /dev/null +++ b/test/test_suite2/compile_time/compile_time_array.c3t @@ -0,0 +1,28 @@ +// #target: macos-x64 +module test; + +fn void test() +{ + var $foo = { 1, "a" }; + var $bar = $foo[0]; + var $i = 1; + var $baz = $foo[$i]; + int x = $bar; + char[] z = $baz; +} + +/* #expect: test.ll + +%"char[]" = type { ptr, i64 } + +@.str = private unnamed_addr constant [2 x i8] c"a\00", align 1 + +; Function Attrs: nounwind +define void @test.test() #0 { +entry: + %x = alloca i32, align 4 + %z = alloca %"char[]", align 8 + store i32 1, ptr %x, align 4 + store %"char[]" { ptr @.str, i64 1 }, ptr %z, align 8 + ret void +} diff --git a/test/test_suite2/compile_time/compile_time_array_ref.c3t b/test/test_suite2/compile_time/compile_time_array_ref.c3t new file mode 100644 index 000000000..05f80290c --- /dev/null +++ b/test/test_suite2/compile_time/compile_time_array_ref.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module foo; + +char[8192] stack; +char* x = &stack[0] + 1000; + +fn void test() +{ + static char[2] y; + static char* z = &y[1]; +} + +/* #expect: foo.ll + +@foo.stack = local_unnamed_addr global [8192 x i8] zeroinitializer, align 16 +@foo.x = local_unnamed_addr global ptr getelementptr (i8, ptr @foo.stack, i64 1000), align 8 +@test.y = internal unnamed_addr global [2 x i8] zeroinitializer, align 1 +@test.z = internal unnamed_addr global ptr getelementptr inbounds ([2 x i8], ptr @test.y, i64 0, i64 1), align 8 + +; Function Attrs: nounwind +define void @foo.test() #0 { +entry: + ret void +} \ No newline at end of file diff --git a/test/test_suite2/compile_time/compile_time_bitops.c3t b/test/test_suite2/compile_time/compile_time_bitops.c3t new file mode 100644 index 000000000..573a5aac9 --- /dev/null +++ b/test/test_suite2/compile_time/compile_time_bitops.c3t @@ -0,0 +1,18 @@ +// #target: macos-x64 +module foo; + +int x1 = 2 ^ 4; +int x2 = 2 | 4; +int x3 = 2 & 4; +int y1 = 4 << 2; +int y2 = 4 >> 2; +int y3 = ~4; + +/* #expect: foo.ll + +@foo.x1 = local_unnamed_addr global i32 6, align 4 +@foo.x2 = local_unnamed_addr global i32 6, align 4 +@foo.x3 = local_unnamed_addr global i32 0, align 4 +@foo.y1 = local_unnamed_addr global i32 16, align 4 +@foo.y2 = local_unnamed_addr global i32 1, align 4 +@foo.y3 = local_unnamed_addr global i32 -5, align 4 \ No newline at end of file diff --git a/test/test_suite2/compile_time/compile_time_ptr_ref.c3t b/test/test_suite2/compile_time/compile_time_ptr_ref.c3t new file mode 100644 index 000000000..730c96eb3 --- /dev/null +++ b/test/test_suite2/compile_time/compile_time_ptr_ref.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 +module test; + + +int*[] blurp = { &ptr, &ptr, (&ptr + 1), &ptr - 1, (int*)((iptr)(&ptr) - 4) }; +int* c = (int*)((iptr)(&ptr) - 4); +int* c2 = (int*)((iptr)(&ptr) + 4); +int* c3 = (int*)(4 + (iptr)(&ptr)); +iptr ff = (iptr)(&ptr); +int ptr = 0; + +/* #expect: test.ll + +%"int*[]" = type { ptr, i64 } + +@.taddr = private global [5 x ptr] [ptr @test.ptr, ptr @test.ptr, ptr getelementptr inbounds (i32, ptr @test.ptr, i64 1), ptr getelementptr (i32, ptr @test.ptr, i64 -1), ptr getelementptr (i8, ptr @test.ptr, i64 -4)], align 8 +@test.blurp = local_unnamed_addr global %"int*[]" { ptr @.taddr, i64 5 }, align 8 +@test.c = local_unnamed_addr global ptr getelementptr (i8, ptr @test.ptr, i64 -4), align 8 +@test.c2 = local_unnamed_addr global ptr getelementptr (i8, ptr @test.ptr, i64 4), align 8 +@test.c3 = local_unnamed_addr global ptr getelementptr (i8, ptr @test.ptr, i64 4), align 8 +@test.ff = local_unnamed_addr global i64 ptrtoint (ptr @test.ptr to i64), align 8 +@test.ptr = global i32 0, align 4 \ No newline at end of file diff --git a/test/test_suite2/compile_time/ct_eval.c3t b/test/test_suite2/compile_time/ct_eval.c3t new file mode 100644 index 000000000..e9fea6cb2 --- /dev/null +++ b/test/test_suite2/compile_time/ct_eval.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 +module test; +extern fn void printf(char*, ...); + +fn void main() +{ + var $x = "abc"; + int abc = 20; + $eval($x) = 444; + printf("Val: %d\n", $eval("abc")); +} +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %abc = alloca i32, align 4 + store i32 20, ptr %abc, align 4 + store i32 444, ptr %abc, align 4 + %0 = load i32, ptr %abc, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %0) + ret void +} diff --git a/test/test_suite2/compile_time/ct_for.c3t b/test/test_suite2/compile_time/ct_for.c3t new file mode 100644 index 000000000..93dbb262b --- /dev/null +++ b/test/test_suite2/compile_time/ct_for.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 + +module test; + +extern fn void printf(char*, ...); + +fn void main() +{ + + $for (var $i = 0; $i < 3; $i++): + printf("Foo %d\n", $i); + $endfor; + + $for (var $i = 0, var $j = 100; $i < 4;): + printf("Foo %d %d\n", $i++, $j--); + $endfor; + +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + call void (ptr, ...) @printf(ptr @.str, i32 0) + call void (ptr, ...) @printf(ptr @.str.1, i32 1) + call void (ptr, ...) @printf(ptr @.str.2, i32 2) + call void (ptr, ...) @printf(ptr @.str.3, i32 0, i32 100) + call void (ptr, ...) @printf(ptr @.str.4, i32 1, i32 99) + call void (ptr, ...) @printf(ptr @.str.5, i32 2, i32 98) + call void (ptr, ...) @printf(ptr @.str.6, i32 3, i32 97) + ret void +} diff --git a/test/test_suite2/compile_time/ct_foreach.c3t b/test/test_suite2/compile_time/ct_foreach.c3t new file mode 100644 index 000000000..71649bb19 --- /dev/null +++ b/test/test_suite2/compile_time/ct_foreach.c3t @@ -0,0 +1,52 @@ +// #target: macos-x64 +module test; + +extern fn void printf(char*, ...); + +fn void main() +{ + + var $foo = { 1, 10, 34 }; + $foreach ($i : $foo): + printf("Foo %d\n", $i); + $endforeach; + + $foreach ($i, $j : $foo): + printf("Bar %d %d\n", $i, $j); + $endforeach; + + $foreach ($x : { 123, "abc", 1177, "hello" }): + $typeof($x) z = $x; + $switch ($typeof($x)): + $case int: + printf("Bar %d\n", $x); + $default: + printf("Bar %s\n", $x); + $endswitch; + $endforeach; + +} + +/* #expect: test.ll +define void @test.main() #0 { +entry: + %z = alloca i32, align 4 + %z1 = alloca ptr, align 8 + %z2 = alloca i32, align 4 + %z3 = alloca ptr, align 8 + call void (ptr, ...) @printf(ptr @.str, i32 1) + call void (ptr, ...) @printf(ptr @.str.1, i32 10) + call void (ptr, ...) @printf(ptr @.str.2, i32 34) + call void (ptr, ...) @printf(ptr @.str.3, i32 0, i32 1) + call void (ptr, ...) @printf(ptr @.str.4, i32 1, i32 10) + call void (ptr, ...) @printf(ptr @.str.5, i32 2, i32 34) + store i32 123, ptr %z, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 123) + store ptr @.str.7, ptr %z1, align 8 + call void (ptr, ...) @printf(ptr @.str.8, ptr @.str.9) + store i32 1177, ptr %z2, align 4 + call void (ptr, ...) @printf(ptr @.str.10, i32 1177) + store ptr @.str.11, ptr %z3, align 8 + call void (ptr, ...) @printf(ptr @.str.12, ptr @.str.13) + ret void +} diff --git a/test/test_suite2/compile_time/ct_if.c3t b/test/test_suite2/compile_time/ct_if.c3t new file mode 100644 index 000000000..4432be030 --- /dev/null +++ b/test/test_suite2/compile_time/ct_if.c3t @@ -0,0 +1,65 @@ +$if (0): +$else: + $if (0): + $elif (0): + $elif (0): + $else: + int x = 1; + $endif; +$endif; + +$if (0): +$assert(false); +$elif (0): +$assert(false); +$else: +$assert(true); +$endif; + +$if (1): +$assert(true); +int d = 5; +$elif (0): +$assert(false); +$else: +$assert(false); +$endif; + +$if (0): +$assert(true); +$elif (1): +$assert(true); +int c = 5; +$else: +$assert(false); +$endif; + +$if (0): +$assert(true); +$elif (1): +$assert(true); +int b = 4; +$elif (0): +$assert(false); +$else: +$assert(false); +$endif; + +$if (0): +$assert(true); +$elif (0): +$assert(false); +$elif (1): +$assert(true); +int a = 3; +$else: +$assert(false); +$endif; + +// #expect: ct_if.ll + +@ct_if.d = local_unnamed_addr global i32 5, align 4 +@ct_if.c = local_unnamed_addr global i32 5, align 4 +@ct_if.b = local_unnamed_addr global i32 4, align 4 +@ct_if.a = local_unnamed_addr global i32 3, align 4 +@ct_if.x = local_unnamed_addr global i32 1, align 4 \ No newline at end of file diff --git a/test/test_suite2/compile_time/ct_if_fails.c3 b/test/test_suite2/compile_time/ct_if_fails.c3 new file mode 100644 index 000000000..1d582b250 --- /dev/null +++ b/test/test_suite2/compile_time/ct_if_fails.c3 @@ -0,0 +1,28 @@ +int x; +$if (x > 0): +$endif; + +$if (0): + $assert(false); +$endif; + +$if (1): +$else: +$endif; + +$if (1): +$else: +$else: // #error: Expected a top level declaration here. +$endif; + + +$if (1): +$elif (2): +$else: +$endif; + +$if (1): +$elif (2): +$elif (3): +$else: +$endif; diff --git a/test/test_suite2/compile_time/ct_switch.c3t b/test/test_suite2/compile_time/ct_switch.c3t new file mode 100644 index 000000000..cdb8032a2 --- /dev/null +++ b/test/test_suite2/compile_time/ct_switch.c3t @@ -0,0 +1,65 @@ +// #target: macos-x64 + +module test; + +macro getisprime($x) +{ + $switch ($x): + $case 1: + $case 2: + $case 3: + $case 5: + $case 7: + $case 11: + $case 13: + return "prime"; + $case 4: + $case 6: + $case 8: + $case 9: + $case 10: + $case 12: + return "not_prime"; + $case 17: + $default: + return "donnowifprime"; + $endswitch; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + printf("%s\n", getisprime(3)); + printf("%s\n", getisprime(12)); + printf("%s\n", getisprime(4)); + printf("%s\n", getisprime(100)); + printf("%s\n", getisprime(17)); +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.1 = private unnamed_addr constant [6 x i8] c"prime\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.3 = private unnamed_addr constant [10 x i8] c"not_prime\00", align 1 +@.str.4 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.5 = private unnamed_addr constant [10 x i8] c"not_prime\00", align 1 +@.str.6 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.7 = private unnamed_addr constant [14 x i8] c"donnowifprime\00", align 1 +@.str.8 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.9 = private unnamed_addr constant [14 x i8] c"donnowifprime\00", align 1 + +; Function Attrs: nounwind +declare void @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + call void (ptr, ...) @printf(ptr @.str, ptr @.str.1) + call void (ptr, ...) @printf(ptr @.str.2, ptr @.str.3) + call void (ptr, ...) @printf(ptr @.str.4, ptr @.str.5) + call void (ptr, ...) @printf(ptr @.str.6, ptr @.str.7) + call void (ptr, ...) @printf(ptr @.str.8, ptr @.str.9) + ret void +} diff --git a/test/test_suite2/compile_time/ct_switch_errors.c3 b/test/test_suite2/compile_time/ct_switch_errors.c3 new file mode 100644 index 000000000..25f8e381a --- /dev/null +++ b/test/test_suite2/compile_time/ct_switch_errors.c3 @@ -0,0 +1,36 @@ + +fn void test() +{ + $switch (3): + $case 2: + return; + $default: + $default: // #error: More than one $default is not allowed + return; + $endswitch; +} + +fn void test1() +{ + $switch (-1): + $case -1: + return; + $case -1: // #error: '-1' appears more than once + return; + $default: + return; + $endswitch; +} + + +fn void test3() +{ + $switch (3): + $case 3: + return; + $case 123.0: // #error: Implicitly casting 'double' to 'int' is not permitted + return; + $default: + return; + $endswitch; +} \ No newline at end of file diff --git a/test/test_suite2/compile_time/ct_switch_top_level.c3t b/test/test_suite2/compile_time/ct_switch_top_level.c3t new file mode 100644 index 000000000..a16e494bc --- /dev/null +++ b/test/test_suite2/compile_time/ct_switch_top_level.c3t @@ -0,0 +1,54 @@ +// #target: macos-x64 +module test; + +extern fn void printf(char*, ...); + +macro tester() +{ + var $Type = int; + $switch ($Type): + $case int: + printf("Hello\n"); + int z = 0; + $default: + int j = 213; + $endswitch; + +} +$switch (bool.typeid): +$case int: + int oefke = 23; +$default: + int oeoekgokege = 343432; +$endswitch; + +fn int main() +{ + tester(); + tester(); + int i = 1; + return 1; +} + +/* #expect: test.ll + +source_filename = "test" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +@test.oeoekgokege = local_unnamed_addr global i32 343432, align 4 +@.str = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1 +@.str.1 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1 + +define i32 @main() #0 { +entry: + %z = alloca i32, align 4 + %z1 = alloca i32, align 4 + %i = alloca i32, align 4 + call void (ptr, ...) @printf(ptr @.str) + store i32 0, ptr %z, align 4 + call void (ptr, ...) @printf(ptr @.str.1) + store i32 0, ptr %z1, align 4 + store i32 1, ptr %i, align 4 + ret i32 1 +} diff --git a/test/test_suite2/compile_time/ct_switch_type_check.c3t b/test/test_suite2/compile_time/ct_switch_type_check.c3t new file mode 100644 index 000000000..740caf557 --- /dev/null +++ b/test/test_suite2/compile_time/ct_switch_type_check.c3t @@ -0,0 +1,46 @@ +// #target: macos-x64 + +module test; + +macro get_type($Type) +{ + $switch ($Type.typeid): + $case int: + return "int"; + $case double: + return "double"; + $default: + return "any other"; + $endswitch; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + printf("%s\n", get_type(int)); + printf("%s\n", get_type(double)); + printf("%s\n", get_type(bool)); + +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.1 = private unnamed_addr constant [4 x i8] c"int\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.3 = private unnamed_addr constant [7 x i8] c"double\00", align 1 +@.str.4 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.5 = private unnamed_addr constant [10 x i8] c"any other\00", align 1 + +; Function Attrs: nounwind +declare void @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + call void (ptr, ...) @printf(ptr @.str, ptr @.str.1) + call void (ptr, ...) @printf(ptr @.str.2, ptr @.str.3) + call void (ptr, ...) @printf(ptr @.str.4, ptr @.str.5) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/compile_time/ct_switch_type_errors.c3 b/test/test_suite2/compile_time/ct_switch_type_errors.c3 new file mode 100644 index 000000000..2e1dd90e1 --- /dev/null +++ b/test/test_suite2/compile_time/ct_switch_type_errors.c3 @@ -0,0 +1,51 @@ + +fn void test() +{ + $switch (int.typeid): + $case int: + return; + $default: + $default: // #error: More than one $default is not allowed + return; + $endswitch; +} + +fn void test1() +{ + $switch (int.typeid): + $case int: + return; + $case int: // #error: 'int' appears more than once + return; + $default: + return; + $endswitch; +} + +define Foo = int; +define Bar = double; +fn void test2() +{ + $switch (int.typeid): + $case int: + return; + $case Bar: + return; + $case Foo: // #error: 'int' appears more than once + return; + $default: + return; + $endswitch; +} + +fn void test3() +{ + $switch (int.typeid): + $case int: + return; + $case 123: // #error: A type was expected here not 'int' + return; + $default: + return; + $endswitch; +} \ No newline at end of file diff --git a/test/test_suite2/compile_time/cttype_reassign.c3t b/test/test_suite2/compile_time/cttype_reassign.c3t new file mode 100644 index 000000000..ef4e0b1fb --- /dev/null +++ b/test/test_suite2/compile_time/cttype_reassign.c3t @@ -0,0 +1,15 @@ +// #target: macos-x64 +module reassign; + +fn void test() +{ + var $Foo = double; + $Foo = int; + $Foo hello; +} + +// #expect: reassign.ll + + %hello = alloca i32, align 4 + store i32 0, ptr %hello, align 4 + ret void \ No newline at end of file diff --git a/test/test_suite2/compile_time/not_yet_initialized.c3 b/test/test_suite2/compile_time/not_yet_initialized.c3 new file mode 100644 index 000000000..018b02310 --- /dev/null +++ b/test/test_suite2/compile_time/not_yet_initialized.c3 @@ -0,0 +1,17 @@ +macro foo($Foo) +{ + $Foo a; + return a; +} + +fn void test1() +{ + var $Bar; + foo($Bar); // #error: '$Bar' is not defined yet +} + +fn void test2() +{ + var $Bar; + $Bar z; // #error: '$Bar' is not defined yet +} diff --git a/test/test_suite2/compile_time/stringify.c3t b/test/test_suite2/compile_time/stringify.c3t new file mode 100644 index 000000000..33ea827b7 --- /dev/null +++ b/test/test_suite2/compile_time/stringify.c3t @@ -0,0 +1,109 @@ +// #target: macos-x64 +module test; +import libc; +import std::io; + +macro @timeit(#call) +{ + long t = (long)libc::clock(); + var $Type = $typeof(#call); + var $is_void = $Type.typeid == void.typeid; +$if ($is_void): + #call; +$else: + $Type result = #call; +$endif; + long diff = (long)libc::clock() - t; + libc::printf("'%s' took %lld us\n", $stringify(#call), diff); +$if (!$is_void): + return result; +$endif; +} + +fn void test() +{ + for (int i = 0; i < 1000; i++) libc::printf("%d\n", i); +} + +fn void main() +{ + @timeit(test()); + int a = 100; + int x = @timeit(1 + 3 + a); + libc::printf("Result was %d\n", x); +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@.str.1 = private unnamed_addr constant [19 x i8] c"'%s' took %lld us\0A\00", align 1 +@.str.2 = private unnamed_addr constant [7 x i8] c"test()\00", align 1 +@.str.3 = private unnamed_addr constant [19 x i8] c"'%s' took %lld us\0A\00", align 1 +@.str.4 = private unnamed_addr constant [10 x i8] c"1 + 3 + a\00", align 1 +@.str.5 = private unnamed_addr constant [15 x i8] c"Result was %d\0A\00", align 1 + +define void @test.test() #0 { +entry: + %i = alloca i32, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %0 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %0, 1000 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i32, ptr %i, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str, i32 %1) + %3 = load i32, ptr %i, align 4 + %add = add i32 %3, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} + +define void @test.main() #0 { +entry: + %t = alloca i64, align 8 + %diff = alloca i64, align 8 + %a = alloca i32, align 4 + %x = alloca i32, align 4 + %t1 = alloca i64, align 8 + %result = alloca i32, align 4 + %diff2 = alloca i64, align 8 + %0 = call i64 @clock() + store i64 %0, ptr %t, align 8 + call void @test.test() + %1 = call i64 @clock() + %2 = load i64, ptr %t, align 8 + %sub = sub i64 %1, %2 + store i64 %sub, ptr %diff, align 8 + %3 = load i64, ptr %diff, align 8 + %4 = call i32 (ptr, ...) @printf(ptr @.str.1, ptr @.str.2, i64 %3) + store i32 100, ptr %a, align 4 + %5 = call i64 @clock() + store i64 %5, ptr %t1, align 8 + %6 = load i32, ptr %a, align 4 + %add = add i32 4, %6 + store i32 %add, ptr %result, align 4 + %7 = call i64 @clock() + %8 = load i64, ptr %t1, align 8 + %sub3 = sub i64 %7, %8 + store i64 %sub3, ptr %diff2, align 8 + %9 = load i64, ptr %diff2, align 8 + %10 = call i32 (ptr, ...) @printf(ptr @.str.3, ptr @.str.4, i64 %9) + %11 = load i32, ptr %result, align 4 + store i32 %11, ptr %x, align 4 + %12 = load i32, ptr %x, align 4 + %13 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %12) + ret void +} + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} diff --git a/test/test_suite2/compile_time/ternary_folding.c3t b/test/test_suite2/compile_time/ternary_folding.c3t new file mode 100644 index 000000000..79af822c7 --- /dev/null +++ b/test/test_suite2/compile_time/ternary_folding.c3t @@ -0,0 +1,25 @@ +// #target: macos-x64 + +int foo = 2.2 ? 1 : 2; +double bar = false ? 1.0 : 2; +bool baz = 1 ? false : true; + +fn void test() +{ + int x = 1 ? 0 : test2(); +} + +fn int test2() { return 3; } + +// #expect: ternary_folding.ll + +@ternary_folding.foo = local_unnamed_addr global i32 1, align 4 +@ternary_folding.bar = local_unnamed_addr global double 2.000000e+00, align 8 +@ternary_folding.baz = local_unnamed_addr global i8 0, align 1 + +define void @ternary_folding.test() #0 { +entry: + %x = alloca i32, align 4 + store i32 0, ptr %x, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/compile_time/typeof_example.c3t b/test/test_suite2/compile_time/typeof_example.c3t new file mode 100644 index 000000000..5ba86b817 --- /dev/null +++ b/test/test_suite2/compile_time/typeof_example.c3t @@ -0,0 +1,52 @@ +extern fn void printf(char *, ...); + +macro bitcast($Target, value) +{ + $typeof(value) temp = value; + $Target* result = ($Target*)(&temp); + return *result; +} + +fn void main() +{ + float f = 100; + int i = bitcast(int, f); + float f2 = bitcast(float, i); + printf("Bitcast %f to %d to %f", f, i, f2); +} + +/* #expect: typeof_example.ll + + %f = alloca float, align 4 + %i = alloca i32, align 4 + %value = alloca float, align 4 + %temp = alloca float, align 4 + %result = alloca ptr, align 8 + %f2 = alloca float, align 4 + %value1 = alloca i32, align 4 + %temp2 = alloca i32, align 4 + %result3 = alloca ptr, align 8 + store float 1.000000e+02, ptr %f, align 4 + %0 = load float, ptr %f, align 4 + store float %0, ptr %value, align 4 + %1 = load float, ptr %value, align 4 + store float %1, ptr %temp, align 4 + store ptr %temp, ptr %result, align 8 + %2 = load ptr, ptr %result, align 8 + %3 = load i32, ptr %2, align 8 + store i32 %3, ptr %i, align 4 + %4 = load i32, ptr %i, align 4 + store i32 %4, ptr %value1, align 4 + %5 = load i32, ptr %value1, align 4 + store i32 %5, ptr %temp2, align 4 + store ptr %temp2, ptr %result3, align 8 + %6 = load ptr, ptr %result3, align 8 + %7 = load float, ptr %6, align 8 + store float %7, ptr %f2, align 4 + %8 = load float, ptr %f, align 4 + %fpfpext = fpext float %8 to double + %9 = load i32, ptr %i, align 4 + %10 = load float, ptr %f2, align 4 + %fpfpext4 = fpext float %10 to double + call void (ptr, ...) @printf(ptr @.str, double %fpfpext, i32 %9, double %fpfpext4) + ret void \ No newline at end of file diff --git a/test/test_suite2/compile_time/typeof_from_literal.c3 b/test/test_suite2/compile_time/typeof_from_literal.c3 new file mode 100644 index 000000000..f4bbb82e4 --- /dev/null +++ b/test/test_suite2/compile_time/typeof_from_literal.c3 @@ -0,0 +1,14 @@ +module foo; + +fn void a() +{ + $typeof(9146744073709551615i64) ef; + int fffx = ef; // #error: 'long' to 'int' +} + +fn void b() +{ + $typeof(9223372036854775809u64) ef; + int fffx = ef; // #error: 'ulong' to 'int' +} + diff --git a/test/test_suite2/compile_time_introspection/alignof.c3t b/test/test_suite2/compile_time_introspection/alignof.c3t new file mode 100644 index 000000000..42cd77311 --- /dev/null +++ b/test/test_suite2/compile_time_introspection/alignof.c3t @@ -0,0 +1,90 @@ +// #target: macos-x64 +module foo; + +int[100] zfe; +struct Bob +{ + Bob[] x; + char[100] y; + struct w { + int z; + } +} + +union Ex +{ + char[8] c; + int[2] y; + double z; +} + +union Br +{ + int y; + char x; +} +struct Ar +{ + long z; + Br[10] br; +} + +union Foob +{ + long a; + char[8] c; +} +Ar izzy; + + +long x = $alignof(zfe); +short y = $alignof(Bob.y); +int z = $alignof(Bob.y); +int w = $alignof(Bob.y); +int v = $alignof(v); +int x1 = $alignof(Ex.c); +int x2 = $alignof(Ex.y); +int x3 = $alignof(char[8]); +int x4 = $alignof(Ar.br[1]); +int x5 = $alignof(Ar.br[1]); +int x6 = $alignof(Ar.br[1]); +int x7 = $alignof(Ar.br[1]); +int x8 = $alignof(Ar.br[2]); +int x9 = $alignof(izzy.br[1]); +int x10 = $alignof(izzy.br[1]); +int x11 = $alignof(izzy.br[1]); +int z0 = $alignof(Foob.c); +int z00 = $alignof(Foob.c[0]); +int z01 = $alignof(Foob.c[1]); +int z02 = $alignof(Foob.c[2]); +int z03 = $alignof(Foob.c[3]); +int z04 = $alignof(Foob.c[4]); +int z05 = $alignof(Foob.c[5]); + + + +// #expect: foo.ll + +@foo.x = local_unnamed_addr global i64 16, align 8 +@foo.y = local_unnamed_addr global i16 8, align 2 +@foo.z = local_unnamed_addr global i32 8, align 4 +@foo.w = local_unnamed_addr global i32 8, align 4 +@foo.v = local_unnamed_addr global i32 4, align 4 +@foo.x1 = local_unnamed_addr global i32 8, align 4 +@foo.x2 = local_unnamed_addr global i32 8, align 4 +@foo.x3 = local_unnamed_addr global i32 1, align 4 +@foo.x4 = local_unnamed_addr global i32 4, align 4 +@foo.x5 = local_unnamed_addr global i32 4, align 4 +@foo.x6 = local_unnamed_addr global i32 4, align 4 +@foo.x7 = local_unnamed_addr global i32 4, align 4 +@foo.x8 = local_unnamed_addr global i32 8, align 4 +@foo.x9 = local_unnamed_addr global i32 4, align 4 +@foo.x10 = local_unnamed_addr global i32 4, align 4 +@foo.x11 = local_unnamed_addr global i32 4, align 4 +@foo.z0 = local_unnamed_addr global i32 8, align 4 +@foo.z00 = local_unnamed_addr global i32 8, align 4 +@foo.z01 = local_unnamed_addr global i32 1, align 4 +@foo.z02 = local_unnamed_addr global i32 2, align 4 +@foo.z03 = local_unnamed_addr global i32 1, align 4 +@foo.z04 = local_unnamed_addr global i32 4, align 4 +@foo.z05 = local_unnamed_addr global i32 1, align 4 \ No newline at end of file diff --git a/test/test_suite2/compile_time_introspection/defined.c3t b/test/test_suite2/compile_time_introspection/defined.c3t new file mode 100644 index 000000000..452418a72 --- /dev/null +++ b/test/test_suite2/compile_time_introspection/defined.c3t @@ -0,0 +1,97 @@ +// #target: macos-x64 + +module mymodule; + +extern fn void printf(char *, ...); + +struct Foo +{ + int a; + int ab; + struct bob + { + int j; + } +} +fn void main() +{ + int x = 0; + var $counter = 0; + $if ($defined(x)): + x++; + $counter++; + $endif; + $if ($defined(Foo.ab)): + int y = 10; + $counter++; + x++; + $endif; + $if ($defined(Foo.ab.x)): + x = 0; + $counter = 0; + $endif; + $if ($defined(Foo.bob)): + x++; + $counter++; + $endif; + $if ($defined($eval("x"))): + x++; + $counter++; + $endif; + $if ($defined($evaltype("Foo").$eval("ab"))): + x++; + $counter++; + $endif; + $if ($defined($evaltype("mymodule::Foo").$eval("bob"))): + x++; + $counter++; + $endif; + $if ($defined(y)): + x++; + $counter++; + y = 1; + $endif; + $if ($defined(z)): + $counter = 0; + x = 0; + $endif; + int z = $counter; + printf("%d\n", x); +} + +/* #expect: mymodule.ll + +define void @mymodule.main() #0 { +entry: + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %z = alloca i32, align 4 + store i32 0, ptr %x, align 4 + %0 = load i32, ptr %x, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr %x, align 4 + store i32 10, ptr %y, align 4 + %1 = load i32, ptr %x, align 4 + %add1 = add i32 %1, 1 + store i32 %add1, ptr %x, align 4 + %2 = load i32, ptr %x, align 4 + %add2 = add i32 %2, 1 + store i32 %add2, ptr %x, align 4 + %3 = load i32, ptr %x, align 4 + %add3 = add i32 %3, 1 + store i32 %add3, ptr %x, align 4 + %4 = load i32, ptr %x, align 4 + %add4 = add i32 %4, 1 + store i32 %add4, ptr %x, align 4 + %5 = load i32, ptr %x, align 4 + %add5 = add i32 %5, 1 + store i32 %add5, ptr %x, align 4 + %6 = load i32, ptr %x, align 4 + %add6 = add i32 %6, 1 + store i32 %add6, ptr %x, align 4 + store i32 1, ptr %y, align 4 + store i32 7, ptr %z, align 4 + %7 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %7) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/compile_time_introspection/defined_builtin.c3t b/test/test_suite2/compile_time_introspection/defined_builtin.c3t new file mode 100644 index 000000000..c7dc9d835 --- /dev/null +++ b/test/test_suite2/compile_time_introspection/defined_builtin.c3t @@ -0,0 +1,18 @@ +// #target: macos-x64 +module foo; +fn void test() +{ + bool a = $defined($$sin); + bool b = $defined($$bas); +} + +/* #expect: foo.ll + +define void @foo.test() #0 { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 1, ptr %a, align 1 + store i8 0, ptr %b, align 1 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/compile_time_introspection/defined_err.c3 b/test/test_suite2/compile_time_introspection/defined_err.c3 new file mode 100644 index 000000000..ae06b4be9 --- /dev/null +++ b/test/test_suite2/compile_time_introspection/defined_err.c3 @@ -0,0 +1,25 @@ +fn void test1() +{ + bool x = $defined(1); // #error: Expected an identifier here +} + +struct Foo +{ + int x; +} + +fn void test2() +{ + $assert($defined(int[1])); + bool x = $defined(int[y]); // #error: 'y' could not be found, did you spell it right? +} + +fn void test3() +{ + $assert($defined(Foo[1])); + $assert($defined(Foo*)); + $assert($defined(Foo[])); + $assert($defined(Foo[*])); + bool x = $defined(Foo[y]); // #error: 'y' could not be found, did you spell it right? +} + diff --git a/test/test_suite2/compile_time_introspection/nameof.c3t b/test/test_suite2/compile_time_introspection/nameof.c3t new file mode 100644 index 000000000..15955b697 --- /dev/null +++ b/test/test_suite2/compile_time_introspection/nameof.c3t @@ -0,0 +1,68 @@ +// #target: macos-x64 +module mymodule; + +extern fn void printf(char *, ...); + +struct Foo { int y; } + +int b; + +fn void main() +{ + printf("%s\n", $qnameof(Foo)); + printf("%s\n", $qnameof($evaltype("Foo"))); + printf("%s\n", $nameof(Foo)); + printf("%s\n", $nameof($evaltype("mymodule::Foo"))); + printf("%s\n", $extnameof(Foo)); + printf("%s\n", $extnameof($evaltype("Foo"))); + + printf("%s\n", $qnameof(b)); + printf("%s\n", $qnameof($eval("b"))); + printf("%s\n", $nameof(b)); + printf("%s\n", $nameof($eval("mymodule::b"))); + printf("%s\n", $extnameof(b)); + printf("%s\n", $extnameof($eval("b"))); + + int a; + + printf("%s\n", $qnameof(a)); + printf("%s\n", $qnameof($eval("a"))); + printf("%s\n", $nameof(a)); + printf("%s\n", $nameof($eval("a"))); + +} + +/* #expect: mymodule.ll + +@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.1 = private unnamed_addr constant [14 x i8] c"mymodule::Foo\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.3 = private unnamed_addr constant [14 x i8] c"mymodule::Foo\00", align 1 +@.str.4 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.5 = private unnamed_addr constant [4 x i8] c"Foo\00", align 1 +@.str.6 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.7 = private unnamed_addr constant [4 x i8] c"Foo\00", align 1 +@.str.8 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.9 = private unnamed_addr constant [13 x i8] c"mymodule.Foo\00", align 1 +@.str.10 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.11 = private unnamed_addr constant [13 x i8] c"mymodule.Foo\00", align 1 +@.str.12 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.13 = private unnamed_addr constant [12 x i8] c"mymodule::b\00", align 1 +@.str.14 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.15 = private unnamed_addr constant [12 x i8] c"mymodule::b\00", align 1 +@.str.16 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.17 = private unnamed_addr constant [2 x i8] c"b\00", align 1 +@.str.18 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.19 = private unnamed_addr constant [2 x i8] c"b\00", align 1 +@.str.20 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.21 = private unnamed_addr constant [11 x i8] c"mymodule.b\00", align 1 +@.str.22 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.23 = private unnamed_addr constant [11 x i8] c"mymodule.b\00", align 1 +@.str.24 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.25 = private unnamed_addr constant [2 x i8] c"a\00", align 1 +@.str.26 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.27 = private unnamed_addr constant [2 x i8] c"a\00", align 1 +@.str.28 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.29 = private unnamed_addr constant [2 x i8] c"a\00", align 1 +@.str.30 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 +@.str.31 = private unnamed_addr constant [2 x i8] c"a\00", align 1 \ No newline at end of file diff --git a/test/test_suite2/compile_time_introspection/nameof_err.c3 b/test/test_suite2/compile_time_introspection/nameof_err.c3 new file mode 100644 index 000000000..bcfacfaef --- /dev/null +++ b/test/test_suite2/compile_time_introspection/nameof_err.c3 @@ -0,0 +1,20 @@ +fn void main() +{ + int a; + $extnameof(a); // #error: 'a' does not have an external name. +} +fn void main2() +{ + int a; + $extnameof($eval("a")); // #error: 'a' does not have an external name. +} + +fn void main3() +{ + $extnameof($evaltype("int")); // #error: Only user defined types have an external name. +} + +fn void main4() +{ + $extnameof($evaltype("foo::int")); // #error: Built in types cannot have a path prefix. +} diff --git a/test/test_suite2/compile_time_introspection/offsetof.c3t b/test/test_suite2/compile_time_introspection/offsetof.c3t new file mode 100644 index 000000000..456bb1cb8 --- /dev/null +++ b/test/test_suite2/compile_time_introspection/offsetof.c3t @@ -0,0 +1,70 @@ +// #target: macos-x64 +module foo; + +int[100] zfe; +struct Bob +{ + Bob[] x; + char[100] y; + struct w { + int z; + } +} + +union Ex +{ + char[8] c; + int[2] y; + double z; +} + +struct Br +{ + int y; + char x; +} +struct Ar +{ + long z; + Br[10] br; +} + +union Foob +{ + long a; + char[8] c; +} + + +short y = $offsetof(Bob.y); +int z = $offsetof(Bob.y); +int w = $offsetof(Bob.y); +int x1 = $offsetof(Ex.c[3]); +int x2 = $offsetof(Ex.y[1]); +int x4 = $offsetof(Ar.br[1]); +int x6 = $offsetof(Ar.br[1].x); +int x5 = $offsetof(Ar.br[1]); +int x7 = $offsetof(Ar.br[2].x); +int x8 = $offsetof(Ar.br[2]); +int z0 = $offsetof(Foob.c); +int z00 = $offsetof(Foob.c[0]); +int z01 = $offsetof(Foob.c[1]); +int z02 = $offsetof(Foob.c[5]); +int z03 = $offsetof(Foob.a); + +// #expect: foo.ll +@foo.y = local_unnamed_addr global i16 16, align 2 +@foo.z = local_unnamed_addr global i32 16, align 4 +@foo.w = local_unnamed_addr global i32 16, align 4 +@foo.x1 = local_unnamed_addr global i32 3, align 4 +@foo.x2 = local_unnamed_addr global i32 4, align 4 +@foo.x4 = local_unnamed_addr global i32 16, align 4 +@foo.x6 = local_unnamed_addr global i32 20, align 4 +@foo.x5 = local_unnamed_addr global i32 16, align 4 +@foo.x7 = local_unnamed_addr global i32 28, align 4 +@foo.x8 = local_unnamed_addr global i32 24, align 4 +@foo.z0 = local_unnamed_addr global i32 0, align 4 +@foo.z00 = local_unnamed_addr global i32 0, align 4 +@foo.z01 = local_unnamed_addr global i32 1, align 4 +@foo.z02 = local_unnamed_addr global i32 5, align 4 +@foo.z03 = local_unnamed_addr global i32 0, align 4 diff --git a/test/test_suite2/compile_time_introspection/qnameof.c3t b/test/test_suite2/compile_time_introspection/qnameof.c3t new file mode 100644 index 000000000..f02d63c9b --- /dev/null +++ b/test/test_suite2/compile_time_introspection/qnameof.c3t @@ -0,0 +1,59 @@ +module qnametest; + +extern fn int printf(char *, ...); +int x; + +struct Blob { int z; int f; } + +fn void main() +{ + int help; + printf("printf: %s\n", $nameof(printf)); + printf("printfq: %s\n", $qnameof(printf)); + printf("Blobq: %s\n", $qnameof(Blob)); + printf("Blob: %s\n", $nameof(Blob)); + printf("xq: %s\n", $qnameof(x)); + printf("x: %s\n", $nameof(x)); + printf("helpq: %s\n", $qnameof(help)); + printf("mainq: %s\n", $qnameof(main)); + printf("Blob**[3]: %s\n", $nameof(Blob**[3])); +} + +/* #expect: qnametest.ll + +@.typeid.qnametest.Blob = linkonce constant { i8, i64 } { i8 10, i64 2 }, comdat, align 8 +@qnametest.x = local_unnamed_addr global i32 0, align 4 +@.str = private unnamed_addr constant [12 x i8] c"printf: %s\0A\00", align 1 +@.str.1 = private unnamed_addr constant [7 x i8] c"printf\00", align 1 +@.str.2 = private unnamed_addr constant [13 x i8] c"printfq: %s\0A\00", align 1 +@.str.3 = private unnamed_addr constant [18 x i8] c"qnametest::printf\00", align 1 +@.str.4 = private unnamed_addr constant [11 x i8] c"Blobq: %s\0A\00", align 1 +@.str.5 = private unnamed_addr constant [16 x i8] c"qnametest::Blob\00", align 1 +@.str.6 = private unnamed_addr constant [10 x i8] c"Blob: %s\0A\00", align 1 +@.str.7 = private unnamed_addr constant [5 x i8] c"Blob\00", align 1 +@.str.8 = private unnamed_addr constant [8 x i8] c"xq: %s\0A\00", align 1 +@.str.9 = private unnamed_addr constant [13 x i8] c"qnametest::x\00", align 1 +@.str.10 = private unnamed_addr constant [7 x i8] c"x: %s\0A\00", align 1 +@.str.11 = private unnamed_addr constant [2 x i8] c"x\00", align 1 +@.str.12 = private unnamed_addr constant [11 x i8] c"helpq: %s\0A\00", align 1 +@.str.13 = private unnamed_addr constant [5 x i8] c"help\00", align 1 +@.str.14 = private unnamed_addr constant [11 x i8] c"mainq: %s\0A\00", align 1 +@.str.15 = private unnamed_addr constant [16 x i8] c"qnametest::main\00", align 1 +@.str.16 = private unnamed_addr constant [15 x i8] c"Blob**[3]: %s\0A\00", align 1 +@.str.17 = private unnamed_addr constant [10 x i8] c"Blob**[3]\00", align 1 + +define void @qnametest.main() #0 { +entry: + %help = alloca i32, align 4 + store i32 0, ptr %help, align 4 + %0 = call i32 (ptr, ...) @printf(ptr @.str, ptr @.str.1) + %1 = call i32 (ptr, ...) @printf(ptr @.str.2, ptr @.str.3) + %2 = call i32 (ptr, ...) @printf(ptr @.str.4, ptr @.str.5) + %3 = call i32 (ptr, ...) @printf(ptr @.str.6, ptr @.str.7) + %4 = call i32 (ptr, ...) @printf(ptr @.str.8, ptr @.str.9) + %5 = call i32 (ptr, ...) @printf(ptr @.str.10, ptr @.str.11) + %6 = call i32 (ptr, ...) @printf(ptr @.str.12, ptr @.str.13) + %7 = call i32 (ptr, ...) @printf(ptr @.str.14, ptr @.str.15) + %8 = call i32 (ptr, ...) @printf(ptr @.str.16, ptr @.str.17) + ret void +} diff --git a/test/test_suite2/compile_time_introspection/sizeof.c3t b/test/test_suite2/compile_time_introspection/sizeof.c3t new file mode 100644 index 000000000..772d36ae2 --- /dev/null +++ b/test/test_suite2/compile_time_introspection/sizeof.c3t @@ -0,0 +1,66 @@ +module foo; +import bar; +import bar::abc; + +long x = Baz.sizeof; +short y = $evaltype("Baz").sizeof; +int z = bar::Baz.sizeof; +int w = bar::Baz.sizeof; +int v = bar::abc::Foo.sizeof; +int x1 = $sizeof(x); +int y1 = $sizeof($eval("y")); +int a = Baz.y.sizeof; +int b = $evaltype("Deep").a.$eval("b").sizeof; +int c = Deep.a.b.c.sizeof; +int d = Deep[][100].sizeof; +int e = $evaltype("Deep")[][100]**[100][]*.sizeof; +int a2 = Baz.y.sizeof; +int a3 = Baz.y.sizeof; +int a4 = Baz.y.sizeof; +int a5 = Baz.y.sizeof; + +module bar; + +struct Deep +{ + int x; + struct a + { + struct b + { + char[5] c; + } + } +} + +struct Baz +{ + int x; + char[60] y; +} + +module bar::abc; + +struct Foo +{ + char x; +} + +// #expect: foo.ll + +@foo.x = local_unnamed_addr global i64 64, align 8 +@foo.y = local_unnamed_addr global i16 64, align 2 +@foo.z = local_unnamed_addr global i32 64, align 4 +@foo.w = local_unnamed_addr global i32 64, align 4 +@foo.v = local_unnamed_addr global i32 1, align 4 +@foo.x1 = local_unnamed_addr global i32 8, align 4 +@foo.y1 = local_unnamed_addr global i32 2, align 4 +@foo.a = local_unnamed_addr global i32 60, align 4 +@foo.b = local_unnamed_addr global i32 5, align 4 +@foo.c = local_unnamed_addr global i32 5, align 4 +@foo.d = local_unnamed_addr global i32 1600, align 4 +@foo.e = local_unnamed_addr global i32 8, align 4 +@foo.a2 = local_unnamed_addr global i32 60, align 4 +@foo.a3 = local_unnamed_addr global i32 60, align 4 +@foo.a4 = local_unnamed_addr global i32 60, align 4 +@foo.a5 = local_unnamed_addr global i32 60, align 4 \ No newline at end of file diff --git a/test/test_suite2/compile_time_introspection/sizeof_errors.c3 b/test/test_suite2/compile_time_introspection/sizeof_errors.c3 new file mode 100644 index 000000000..a86de52ed --- /dev/null +++ b/test/test_suite2/compile_time_introspection/sizeof_errors.c3 @@ -0,0 +1,67 @@ +module foo; +import bar; +import bar::abc; + +fn void a() +{ + int x = Bazy.sizeof; // #error: 'Bazy' could not be found, did you spell it right +} + +fn void b() +{ + int x = $evaltype("Bazz").sizeof; // #error: 'Bazz' could not be found, did you spell it rig +} + + +fn void e() +{ + int x = bar::Baze.sizeof; // #error: 'bar::Baze' could not be found, did you spell it right +} + +fn void f() +{ + int x = $evaltype("bar::Bazy").sizeof; // #error: 'bar::Bazy' could not be found +} + +fn void g() +{ + int x = $evaltype("bar::").sizeof; // #error: A valid name was expected here. +} + +fn void k() +{ + int v = $evaltype("int").x.sizeof; // #error: 'int' does not have a property 'x'. +} + +fn void l() +{ + int v = $sizeof(int[].len); // #error: 'int[]' does not have a property 'len' +} + +fn void m() +{ + int v = $sizeof(int[4].len); // #error: 'int[4]' does not have a property 'len' +} + +fn void n() +{ + int v = Baz.x1.sizeof; // #error: No method or inner struct/union 'Baz.x1' found. +} + + + +module bar; + +struct Baz +{ + int x; + char[60] y; +} + +module bar::abc; + +struct Foo +{ + char x; +} + diff --git a/test/test_suite2/constants/byte_literal_fail_base64.c3 b/test/test_suite2/constants/byte_literal_fail_base64.c3 new file mode 100644 index 000000000..ce3837ea6 --- /dev/null +++ b/test/test_suite2/constants/byte_literal_fail_base64.c3 @@ -0,0 +1 @@ +char[*] foo64 = b64"SGVsbG8g!V29ybGQ="; // #error: '!' is not a valid base64 character \ No newline at end of file diff --git a/test/test_suite2/constants/byte_literal_fail_base64_2.c3 b/test/test_suite2/constants/byte_literal_fail_base64_2.c3 new file mode 100644 index 000000000..443883c14 --- /dev/null +++ b/test/test_suite2/constants/byte_literal_fail_base64_2.c3 @@ -0,0 +1 @@ +char[*] foo64 = b64"SGVsbG8gV29y=bGQ="; // #error: 'b' can't be placed after an ending '=' \ No newline at end of file diff --git a/test/test_suite2/constants/byte_literal_fail_base64_4.c3 b/test/test_suite2/constants/byte_literal_fail_base64_4.c3 new file mode 100644 index 000000000..ab8705d22 --- /dev/null +++ b/test/test_suite2/constants/byte_literal_fail_base64_4.c3 @@ -0,0 +1 @@ +char[*] foo64 = b64"SGVsbG8gV29ybGQ==="; // #error: There cannot be more than \ No newline at end of file diff --git a/test/test_suite2/constants/byte_literal_fail_hex.c3 b/test/test_suite2/constants/byte_literal_fail_hex.c3 new file mode 100644 index 000000000..115e3d4ba --- /dev/null +++ b/test/test_suite2/constants/byte_literal_fail_hex.c3 @@ -0,0 +1 @@ +char[*] foo64 = x"abc def ^"; // #error: '^' isn't a valid hexadecimal digit, all digits should be a-z, A-Z and 0-9. diff --git a/test/test_suite2/constants/byte_literals.c3t b/test/test_suite2/constants/byte_literals.c3t new file mode 100644 index 000000000..1a68db76d --- /dev/null +++ b/test/test_suite2/constants/byte_literals.c3t @@ -0,0 +1,13 @@ +char[*] foob = x"a0"; +char[*] fooz = x"00aabbccddeeff"; +char[*] fooy = x'dead beef'; +char[*] foow = x"4549234d e d"; +char[*] foo64 = b64"SGVsbG8gV29ybGQ="; + +// #expect: byte_literals.ll + +@byte_literals.foob = local_unnamed_addr global [1 x i8] c"\A0", align 1 +@byte_literals.fooz = local_unnamed_addr global [7 x i8] c"\00\AA\BB\CC\DD\EE\FF", align 1 +@byte_literals.fooy = local_unnamed_addr global [4 x i8] c"\DE\AD\BE\EF", align 1 +@byte_literals.foow = local_unnamed_addr global [5 x i8] c"EI#M\ED", align 1 +@byte_literals.foo64 = local_unnamed_addr global [11 x i8] c"Hello World", align 1 diff --git a/test/test_suite2/constants/char_literals.c3t b/test/test_suite2/constants/char_literals.c3t new file mode 100644 index 000000000..c4bbb0d6b --- /dev/null +++ b/test/test_suite2/constants/char_literals.c3t @@ -0,0 +1,24 @@ +// #file: file1.c3 +module test; + +char a = ' '; +char b = '\r'; +char c = '\t'; +char d = '\n'; +char e = '\0'; +char f = '\''; +char g = '"'; +char h = '\\'; +char i = '\e'; + +// #expect: test.ll + +@test.a = local_unnamed_addr global i8 32, align 1 +@test.b = local_unnamed_addr global i8 13, align 1 +@test.c = local_unnamed_addr global i8 9, align 1 +@test.d = local_unnamed_addr global i8 10, align 1 +@test.e = local_unnamed_addr global i8 0, align 1 +@test.f = local_unnamed_addr global i8 39, align 1 +@test.g = local_unnamed_addr global i8 34, align 1 +@test.h = local_unnamed_addr global i8 92, align 1 +@test.i = local_unnamed_addr global i8 27, align 1 diff --git a/test/test_suite2/constants/const_var_copy.c3t b/test/test_suite2/constants/const_var_copy.c3t new file mode 100644 index 000000000..739041889 --- /dev/null +++ b/test/test_suite2/constants/const_var_copy.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module foo; +const char[100] FOO = { [50] = 1 }; +const int[<4>] BAR = { 1, 2, 3, 4 }; + +fn void test(int z) +{ + char s = FOO[z]; + int zd = BAR[z]; +} + +/* #expect: foo.ll + +@foo.FOO = local_unnamed_addr constant { [50 x i8], i8, [49 x i8] } { [50 x i8] zeroinitializer, i8 1, [49 x i8] zeroinitializer }, align 16 +@foo.BAR = local_unnamed_addr constant <4 x i32> , align 16 + +define void @foo.test(i32 %0) #0 { +entry: + %s = alloca i8, align 1 + %zd = alloca i32, align 4 + %sisiext = sext i32 %0 to i64 + %1 = getelementptr inbounds [100 x i8], ptr @foo.FOO, i64 0, i64 %sisiext + %2 = load i8, ptr %1, align 1 + store i8 %2, ptr %s, align 1 + %sisiext1 = sext i32 %0 to i64 + %3 = extractelement <4 x i32> , i64 %sisiext1 + store i32 %3, ptr %zd, align 4 + ret void +} diff --git a/test/test_suite2/constants/constants.c3t b/test/test_suite2/constants/constants.c3t new file mode 100644 index 000000000..99078d3fd --- /dev/null +++ b/test/test_suite2/constants/constants.c3t @@ -0,0 +1,40 @@ +private const char AA = ~(char)(0); +const char BB = 200 ; +private const uint CC = ~(uint)(0); +private const uint DD = FOO; + +private const FOO = ~(uint)(0); + +private uint x = AA; +private uint z = CC; +private char w = (char)(FOO); +private ushort v = (ushort)(FOO); +private uint z2 = DD; + +fn void test() +{ + int xx = FOO; + uint* yy = &&FOO; +} + +/* #expect: constants.ll + +@constants.AA = protected unnamed_addr constant i8 -1, align 1 +@constants.BB = local_unnamed_addr constant i8 -56, align 1 +@constants.CC = protected unnamed_addr constant i32 -1, align 4 +@constants.DD = protected unnamed_addr constant i32 -1, align 4 +@constants.FOO = protected unnamed_addr constant i32 -1, align 4 +@constants.x = protected unnamed_addr global i32 255, align 4 +@constants.z = protected unnamed_addr global i32 -1, align 4 +@constants.w = protected unnamed_addr global i8 -1, align 1 +@constants.v = protected unnamed_addr global i16 -1, align 2 +@constants.z2 = protected unnamed_addr global i32 -1, align 4 + +entry: + %xx = alloca i32, align 4 + %yy = alloca ptr, align 8 + %taddr = alloca i32, align 4 + store i32 -1, ptr %xx, align 4 + store i32 -1, ptr %taddr, align 4 + store ptr %taddr, ptr %yy, align 8 + ret void \ No newline at end of file diff --git a/test/test_suite2/contracts/ct_eval_of_ensure.c3 b/test/test_suite2/contracts/ct_eval_of_ensure.c3 new file mode 100644 index 000000000..1d53e2992 --- /dev/null +++ b/test/test_suite2/contracts/ct_eval_of_ensure.c3 @@ -0,0 +1,16 @@ +module test; +/** + * @ensure return > 100 + */ +fn int test(int baz) +{ + return 1; // #error: @ensure "return > 100" violated. +} + +extern fn void printf(char*, ...); +fn void main(char[][] args) +{ + test(1022); + printf("Hello\n"); +} + diff --git a/test/test_suite2/contracts/pure.c3 b/test/test_suite2/contracts/pure.c3 new file mode 100644 index 000000000..139931e44 --- /dev/null +++ b/test/test_suite2/contracts/pure.c3 @@ -0,0 +1,24 @@ +module inlineme; + +/** + * @pure + */ +fn void test() +{ + int x = 123; + int* y = &x; +} + +int abc; +fn void test2() +{ + abc = 1233; +} + +/** + * @pure + */ +fn void test3() +{ + abc = 1233; // #error: '@pure' functions may not access globals +} \ No newline at end of file diff --git a/test/test_suite2/contracts/pure_calls.c3 b/test/test_suite2/contracts/pure_calls.c3 new file mode 100644 index 000000000..6454bbc97 --- /dev/null +++ b/test/test_suite2/contracts/pure_calls.c3 @@ -0,0 +1,26 @@ +module inlineme; + +/** + * @pure + */ +fn void test() +{ + int x = 123; + int* y = &x; + test3(); + test2() @pure; + test2(); // #error: Only '@pure' functions may be called, you can override this with an attribute +} + +int abc; +fn void test2() +{ + abc = 1233; +} + +/** + * @pure + */ +fn void test3() +{ +} \ No newline at end of file diff --git a/test/test_suite2/contracts/simple_test.c3t b/test/test_suite2/contracts/simple_test.c3t new file mode 100644 index 000000000..0cce0f217 --- /dev/null +++ b/test/test_suite2/contracts/simple_test.c3t @@ -0,0 +1,90 @@ +// #target: macos-x64 + +/** + * @param [inout] foo `test` + * @require baz > 100 `whatever` + * @ensure *foo > 231 +*/ +fn void test(int *foo, int baz) +{ + *foo = 444; +} + +/** + * @param [inout] foo `test` + * @require baz > 100 `whatever` + * @ensure return < 200 +*/ +fn int test2(int *foo, int baz) +{ + *foo = 444; + return baz; +} + +/** + * @require x > 0 + * @ensure return > 0 + **/ +fn int test3(int x) +{ + return x + 1; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + int fooofke; + test(&fooofke, 330); + test2(&fooofke, 150); + test3(123); + printf("Foo: %d\n", fooofke); +} + +/* #expect: simple_test.ll + +define void @simple_test.test(ptr %0, i32 %1) #0 { +entry: + %gt = icmp sgt i32 %1, 100 + call void @llvm.assume(i1 %gt) + store i32 444, ptr %0, align 8 + ret void +} + +define i32 @simple_test.test2(ptr %0, i32 %1) #0 { +entry: + %gt = icmp sgt i32 %1, 100 + call void @llvm.assume(i1 %gt) + store i32 444, ptr %0, align 8 + %lt = icmp slt i32 %1, 200 + call void @llvm.assume(i1 %lt) + ret i32 %1 +} + +define i32 @simple_test.test3(i32 %0) #0 { +entry: + %gt = icmp sgt i32 %0, 0 + call void @llvm.assume(i1 %gt) + %add = add i32 %0, 1 + %gt1 = icmp sgt i32 %add, 0 + call void @llvm.assume(i1 %gt1) + ret i32 %add +} + +define void @simple_test.main() #0 { +entry: + %fooofke = alloca i32, align 4 + store i32 0, ptr %fooofke, align 4 + call void @simple_test.test(ptr %fooofke, i32 330) + %0 = call i32 @simple_test.test2(ptr %fooofke, i32 150) + %1 = call i32 @simple_test.test3(i32 123) + %2 = load i32, ptr %fooofke, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %2) + ret void +} + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @simple_test.main() + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite2/debug_symbols/constants.c3t b/test/test_suite2/debug_symbols/constants.c3t new file mode 100644 index 000000000..37a0229ee --- /dev/null +++ b/test/test_suite2/debug_symbols/constants.c3t @@ -0,0 +1,28 @@ +// #target: macos-x64 +// #debuginfo: yes +private const char AA = 1; +const char BB = 200 ; +private const uint CC = ~(uint)(0); +private const FOO = ~(uint)(0); + +/* #expect: constants.ll + +@constants.AA = protected unnamed_addr constant i8 1, align 1 +@constants.BB = local_unnamed_addr constant i8 -56, align 1 +@constants.CC = protected unnamed_addr constant i32 -1, align 4 +@constants.FOO = protected unnamed_addr constant i32 -1, align 4 + +!llvm.dbg.cu = !{!0} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "c3c", isOptimized: false, runtimeVersion: 1, emissionKind: FullDebug +!1 = !DIFile(filename: "constants.c3", +!DIGlobalVariableExpression +distinct !DIGlobalVariable(name: "AA", linkageName: "constants.AA", scope: !1, file: !1, line: 1 +!DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) +!DIGlobalVariableExpression +distinct !DIGlobalVariable(name: "BB", linkageName: "constants.BB", scope: !1, file: !1, line: 2 +!DIGlobalVariableExpression +distinct !DIGlobalVariable(name: "CC", linkageName: "constants.CC", scope: !1, file: !1, line: 3 +!DIBasicType(name: "uint", size: 32, encoding: DW_ATE_unsigned) +!DIGlobalVariableExpression +distinct !DIGlobalVariable(name: "FOO", linkageName: "constants.FOO", scope: !1, file: !1, line: 4 diff --git a/test/test_suite2/defer/defer_and_expr_block.c3t b/test/test_suite2/defer/defer_and_expr_block.c3t new file mode 100644 index 000000000..af90a083e --- /dev/null +++ b/test/test_suite2/defer/defer_and_expr_block.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*,...); + +fn void main() +{ + defer printf("On exit\n"); + {| + defer printf("Baz\n"); + defer {| + defer printf("Hello!\n"); + defer printf("1\n"); + if (true) return 12; + defer printf("2\n"); + return 34; + |}; + |}; + defer printf("On 2\n"); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %blockret = alloca i32, align 4 + br label %if.then + +if.then: ; preds = %entry + call void (ptr, ...) @printf(ptr @.str) + call void (ptr, ...) @printf(ptr @.str.1) + store i32 12, ptr %blockret, align 4 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.then + call void (ptr, ...) @printf(ptr @.str.5) + call void (ptr, ...) @printf(ptr @.str.6) + call void (ptr, ...) @printf(ptr @.str.7) + ret void +} + diff --git a/test/test_suite2/defer/defer_single_stmt.c3 b/test/test_suite2/defer/defer_single_stmt.c3 new file mode 100644 index 000000000..d6bb0cffc --- /dev/null +++ b/test/test_suite2/defer/defer_single_stmt.c3 @@ -0,0 +1,41 @@ +fn void test1() +{ + while (1) defer foo(); // #error: Looping over a raw 'defer' +} + +fn void test1a() +{ + while (1) { defer foo(); } +} + +fn void test2() +{ + if (1) defer foo(); // #error: An 'if' statement may not be followed by a raw 'defer' +} + +fn void test2a() +{ + if (1) { defer foo(); } +} + +fn void test3() +{ + defer defer foo(); // #error: A defer may not have a body consisting of a raw 'defer' +} + +fn void test3a() +{ + defer { defer foo(); } +} + +fn void test4() +{ + for (;;) defer foo(); // #error: Looping over a raw 'defer' +} + +fn void test4a() +{ + for(;;) { defer foo(); } +} + +fn void foo() {} diff --git a/test/test_suite2/defer/defer_static_var.c3t b/test/test_suite2/defer/defer_static_var.c3t new file mode 100644 index 000000000..05123fbb1 --- /dev/null +++ b/test/test_suite2/defer/defer_static_var.c3t @@ -0,0 +1,205 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*,...); + +fn int foo(int x) +{ + defer + { + static int y = 0; + y++; + printf("Here we go %d\n", y); + } + if (x > 0) return 2; + return x; +} + +macro void foo2(int x) +{ + printf("->%d\n", x); + for (int i = 0; i < 100; i++) + { + defer + { + static int y = 0; + y++; + printf(">%d--%d\n", i, y); + } + if (i == x) break; + printf("--"); + } +} + +fn void main() +{ + foo(1); + foo(2); + foo(-2); + foo2(0); + foo2(1); + foo2(2); +} + +/* #expect: foo.ll + +@foo.y = internal unnamed_addr global i32 0, align 4 +@main.y = internal unnamed_addr global i32 0, align 4 +@main.y.7 = internal unnamed_addr global i32 0, align 4 +@main.y.12 = internal unnamed_addr global i32 0, align 4 + + +define i32 @foo.foo(i32 %0) #0 { +entry: + %gt = icmp sgt i32 %0, 0 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %1 = load i32, ptr @foo.y, align 4 + %add = add i32 %1, 1 + store i32 %add, ptr @foo.y, align 4 + %2 = load i32, ptr @foo.y, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %2) + ret i32 2 + +if.exit: ; preds = %entry + %3 = load i32, ptr @foo.y, align 4 + %add1 = add i32 %3, 1 + store i32 %add1, ptr @foo.y, align 4 + %4 = load i32, ptr @foo.y, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %4) + ret i32 %0 +} + +define void @foo.main() #0 { +entry: + %x = alloca i32, align 4 + %i = alloca i32, align 4 + %x3 = alloca i32, align 4 + %i4 = alloca i32, align 4 + %x15 = alloca i32, align 4 + %i16 = alloca i32, align 4 + %0 = call i32 @foo.foo(i32 1) + %1 = call i32 @foo.foo(i32 2) + %2 = call i32 @foo.foo(i32 -2) + store i32 0, ptr %x, align 4 + %3 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %3) + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %if.exit, %entry + %4 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %4, 100 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %5 = load i32, ptr %i, align 4 + %6 = load i32, ptr %x, align 4 + %eq = icmp eq i32 %5, %6 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + %7 = load i32, ptr @main.y, align 4 + %add = add i32 %7, 1 + store i32 %add, ptr @main.y, align 4 + %8 = load i32, ptr %i, align 4 + %9 = load i32, ptr @main.y, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %8, i32 %9) + br label %loop.exit + +if.exit: ; preds = %loop.body + call void (ptr, ...) @printf(ptr @.str.4) + %10 = load i32, ptr @main.y, align 4 + %add1 = add i32 %10, 1 + store i32 %add1, ptr @main.y, align 4 + %11 = load i32, ptr %i, align 4 + %12 = load i32, ptr @main.y, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %11, i32 %12) + %13 = load i32, ptr %i, align 4 + %add2 = add i32 %13, 1 + store i32 %add2, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %if.then, %loop.cond + store i32 1, ptr %x3, align 4 + %14 = load i32, ptr %x3, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %14) + store i32 0, ptr %i4, align 4 + br label %loop.cond5 + +loop.cond5: ; preds = %if.exit11, %loop.exit + %15 = load i32, ptr %i4, align 4 + %lt6 = icmp slt i32 %15, 100 + br i1 %lt6, label %loop.body7, label %loop.exit14 + +loop.body7: ; preds = %loop.cond5 + %16 = load i32, ptr %i4, align 4 + %17 = load i32, ptr %x3, align 4 + %eq8 = icmp eq i32 %16, %17 + br i1 %eq8, label %if.then9, label %if.exit11 + +if.then9: ; preds = %loop.body7 + %18 = load i32, ptr @main.y.7, align 4 + %add10 = add i32 %18, 1 + store i32 %add10, ptr @main.y.7, align 4 + %19 = load i32, ptr %i4, align 4 + %20 = load i32, ptr @main.y.7, align 4 + call void (ptr, ...) @printf(ptr @.str.8, i32 %19, i32 %20) + br label %loop.exit14 + +if.exit11: ; preds = %loop.body7 + call void (ptr, ...) @printf(ptr @.str.9) + %21 = load i32, ptr @main.y.7, align 4 + %add12 = add i32 %21, 1 + store i32 %add12, ptr @main.y.7, align 4 + %22 = load i32, ptr %i4, align 4 + %23 = load i32, ptr @main.y.7, align 4 + call void (ptr, ...) @printf(ptr @.str.10, i32 %22, i32 %23) + %24 = load i32, ptr %i4, align 4 + %add13 = add i32 %24, 1 + store i32 %add13, ptr %i4, align 4 + br label %loop.cond5 + +loop.exit14: ; preds = %if.then9, %loop.cond5 + store i32 2, ptr %x15, align 4 + %25 = load i32, ptr %x15, align 4 + call void (ptr, ...) @printf(ptr @.str.11, i32 %25) + store i32 0, ptr %i16, align 4 + br label %loop.cond17 + +loop.cond17: ; preds = %if.exit23, %loop.exit14 + %26 = load i32, ptr %i16, align 4 + %lt18 = icmp slt i32 %26, 100 + br i1 %lt18, label %loop.body19, label %loop.exit26 + +loop.body19: ; preds = %loop.cond17 + %27 = load i32, ptr %i16, align 4 + %28 = load i32, ptr %x15, align 4 + %eq20 = icmp eq i32 %27, %28 + br i1 %eq20, label %if.then21, label %if.exit23 + +if.then21: ; preds = %loop.body19 + %29 = load i32, ptr @main.y.12, align 4 + %add22 = add i32 %29, 1 + store i32 %add22, ptr @main.y.12, align 4 + %30 = load i32, ptr %i16, align 4 + %31 = load i32, ptr @main.y.12, align 4 + call void (ptr, ...) @printf(ptr @.str.13, i32 %30, i32 %31) + br label %loop.exit26 + +if.exit23: ; preds = %loop.body19 + call void (ptr, ...) @printf(ptr @.str.14) + %32 = load i32, ptr @main.y.12, align 4 + %add24 = add i32 %32, 1 + store i32 %add24, ptr @main.y.12, align 4 + %33 = load i32, ptr %i16, align 4 + %34 = load i32, ptr @main.y.12, align 4 + call void (ptr, ...) @printf(ptr @.str.15, i32 %33, i32 %34) + %35 = load i32, ptr %i16, align 4 + %add25 = add i32 %35, 1 + store i32 %add25, ptr %i16, align 4 + br label %loop.cond17 + +loop.exit26: ; preds = %if.then21, %loop.cond17 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/defer/defer_with_rethrow.c3 b/test/test_suite2/defer/defer_with_rethrow.c3 new file mode 100644 index 000000000..265f2fa0e --- /dev/null +++ b/test/test_suite2/defer/defer_with_rethrow.c3 @@ -0,0 +1,14 @@ +fn int! foo() +{ return 1; } + + +fn int! bar() +{ + defer { + {| + foo()?; + |}; + } + defer foo()?; // #error: Returns are not allowed inside of defers. + return 1; +} \ No newline at end of file diff --git a/test/test_suite2/defer/defer_with_return.c3 b/test/test_suite2/defer/defer_with_return.c3 new file mode 100644 index 000000000..eeabe94d6 --- /dev/null +++ b/test/test_suite2/defer/defer_with_return.c3 @@ -0,0 +1,10 @@ +fn int! bar() +{ + defer { + {| + return 4; + |}; + } + defer return 3; // #error: Return is not allowed inside of a defer + return 1; +} \ No newline at end of file diff --git a/test/test_suite2/define/common.c3 b/test/test_suite2/define/common.c3 new file mode 100644 index 000000000..8f5452dd0 --- /dev/null +++ b/test/test_suite2/define/common.c3 @@ -0,0 +1,17 @@ +module foo; + +// define = +define standard_foo = __stdin; +define someFunctionIntBool = someFunction; +define FooInt = Foo; +define A_CONST_INT = A_CONST; + +define standard_foo = ofke; // #error: Expected '=' +define fn foo = fef; // #error: An identifier was expected here. +define feokfe = fn void(int); // #error: Expected a function or variable name here +define AOFKE = ofek; // #error: Expected a constant name here +define okfoe = OFKEOK; // #error: Expected a function or variable name here +define Helo = helo; // #error: A type name was expected here +define Helo = OFKE; // #error: A type name was expected here +define helo = Helo; // #error: A type alias must start with an upper case letter and contain at least one lower case letter. +define HELO = Helo; // #error: A type alias must start with an upper case letter and contain at least one lower case letter. diff --git a/test/test_suite2/define/define_name_errors.c3 b/test/test_suite2/define/define_name_errors.c3 new file mode 100644 index 000000000..1694e41e5 --- /dev/null +++ b/test/test_suite2/define/define_name_errors.c3 @@ -0,0 +1,9 @@ + +define int = int; // #error: 'int' is the name of a built-in type and can't be used as an alias. +define main = int; // #error: 'main' is reserved and cannot be used as an alias. + +define hello = int; // #error: A type alias must start with an upper case letter and contain at least one lower case letter +define hello = Foo; // #error: A type alias must start with an upper case letter and contain at least one lower case letter + +define HELLO = int; // #error: A type alias must start with an upper case letter and contain at least one lower case letter +define HELLO = Foo; // #error: A type alias must start with an upper case letter and contain at least one lower case letter \ No newline at end of file diff --git a/test/test_suite2/define/forbidden_defines.c3 b/test/test_suite2/define/forbidden_defines.c3 new file mode 100644 index 000000000..78fc1ce82 --- /dev/null +++ b/test/test_suite2/define/forbidden_defines.c3 @@ -0,0 +1,3 @@ +define Abc = int[*]; // #error: Inferred array types can only be used in declarations with initializers. +define Bcd = anyerr; // #error: 'anyerr' may not be aliased. +define Efd = variant; // #error: 'variant' may not be aliased. diff --git a/test/test_suite2/distinct/distinct_invalid.c3 b/test/test_suite2/distinct/distinct_invalid.c3 new file mode 100644 index 000000000..44c3af955 --- /dev/null +++ b/test/test_suite2/distinct/distinct_invalid.c3 @@ -0,0 +1,8 @@ +fault Error +{} + +define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error + +define Foo3 = distinct void; // #error: create a distinct type from 'void' + +define Foo4 = distinct typeid; // #error: create a distinct type from 'typeid' diff --git a/test/test_suite2/distinct/distinct_struct.c3 b/test/test_suite2/distinct/distinct_struct.c3 new file mode 100644 index 000000000..f7e7b39e0 --- /dev/null +++ b/test/test_suite2/distinct/distinct_struct.c3 @@ -0,0 +1,28 @@ + +struct Struct +{ + int x; + double y; +} + +define Foo = distinct Struct; + +struct Struct2 +{ + Foo f; + int d; + struct bar + { + Foo x; + } +} +Foo f = { 1, 1.0 }; + +fn void test(int x) +{ + Struct s = { 1, 2.0 }; + Foo f2 = (Foo)(s); + Foo f3 = { .x = 1 }; + Struct2 s2 = { .f = { 1, 2.0 } }; + Struct2 s3 = { .bar.x.y = 3.0 }; +} \ No newline at end of file diff --git a/test/test_suite2/distinct/distinct_struct_array.c3 b/test/test_suite2/distinct/distinct_struct_array.c3 new file mode 100644 index 000000000..9794d6363 --- /dev/null +++ b/test/test_suite2/distinct/distinct_struct_array.c3 @@ -0,0 +1,19 @@ +module test; + +define Foo = distinct int; + +struct Struct +{ + Foo x; + int y; +} + +define Struct2 = distinct Struct; +define StructArr = distinct Struct2[3]; + +fn void test(int x) +{ + StructArr z = { { .x = 1 }, { .y = x }, { 1, 2 }}; + usize len = z.len; + Foo zz = z[2].x; +} diff --git a/test/test_suite2/distinct/distinct_union.c3 b/test/test_suite2/distinct/distinct_union.c3 new file mode 100644 index 000000000..49af50a55 --- /dev/null +++ b/test/test_suite2/distinct/distinct_union.c3 @@ -0,0 +1,34 @@ +module test; + +union Union +{ + int x; + double y; +} + +define Foo = distinct Union; + +union Union2 +{ + Foo f; + int d; + struct bar + { + Foo x; + } +} +Foo f = { .x = 1 }; + +define Union3 = distinct Union2; + +define UnionArr = distinct Union3[3]; + +fn void test(int x) +{ + Union s = { .y = 2.0 }; + Foo f2 = (Foo)(s); + Foo f3 = { .x = 1 }; + Union2 s2 = { .f = { .y = 1 } }; + Union2 s3 = { .bar.x.y = 3.0 }; + UnionArr a = { [0].bar.x.x = 100 }; +} diff --git a/test/test_suite2/distinct/test_errors.c3 b/test/test_suite2/distinct/test_errors.c3 new file mode 100644 index 000000000..ccea22f84 --- /dev/null +++ b/test/test_suite2/distinct/test_errors.c3 @@ -0,0 +1,11 @@ +module test; + +define Int2 = distinct int; + +fn void test() +{ + Int2 a = 1; + a = a + 1; + int b; + a = b; // #error: 'int' to 'Int2' +} \ No newline at end of file diff --git a/test/test_suite2/distinct/test_ops_on_int.c3 b/test/test_suite2/distinct/test_ops_on_int.c3 new file mode 100644 index 000000000..76f50b233 --- /dev/null +++ b/test/test_suite2/distinct/test_ops_on_int.c3 @@ -0,0 +1,29 @@ +module test; + +define Foo = distinct int; + +fn int test1() +{ + Foo x = 1; + x += 2; + Foo y = 3; + y = x + y; + int z = 4; + y += (Foo)(z); + y = y << z; + y = y >> z; + y = y + y; + y = y - y; + y = y * y; + y = y / y; + y = y & y; + y = y ^ y; + y = y | y; + bool a1 = y != y; + bool a2 = y < y; + bool a3 = y <= y; + bool a4 = y == y; + y = y == 1 ? 1 : y; + y = y < (y + 1) ? 1 : y; + return (int)(y); +} diff --git a/test/test_suite2/distinct/test_ops_on_struct.c3 b/test/test_suite2/distinct/test_ops_on_struct.c3 new file mode 100644 index 000000000..8afcb4962 --- /dev/null +++ b/test/test_suite2/distinct/test_ops_on_struct.c3 @@ -0,0 +1,24 @@ +module test; + +struct Struct +{ + int x; + double y; +} + +define Foo = distinct Struct; + +struct Struct2 +{ + Foo f; + int d; +} +Foo f = { 1, 1.0 }; + +fn void test(int x) +{ + Struct s = { 1, 2.0 }; + Foo f2 = (Foo)(s); + Foo f3 = { .x = 1 }; + Struct2 s2 = { .f = { 1, 2.0 } }; +} \ No newline at end of file diff --git a/test/test_suite2/enumerations/compile_time.c3t b/test/test_suite2/enumerations/compile_time.c3t new file mode 100644 index 000000000..e014657f8 --- /dev/null +++ b/test/test_suite2/enumerations/compile_time.c3t @@ -0,0 +1,16 @@ +enum MyEnum : short +{ + HELO, + WORLD, + BYE +} + +int myenum_elements = MyEnum.elements; +int myenum_alignof = $alignof(MyEnum); +int myenum_sizeof = MyEnum.sizeof; + +// #expect: compile_time.ll + +@compile_time.myenum_elements = local_unnamed_addr global i32 3, align 4 +@compile_time.myenum_alignof = local_unnamed_addr global i32 2, align 4 +@compile_time.myenum_sizeof = local_unnamed_addr global i32 2, align 4 \ No newline at end of file diff --git a/test/test_suite2/enumerations/enum_associated_value.c3t b/test/test_suite2/enumerations/enum_associated_value.c3t new file mode 100644 index 000000000..86fc26a1e --- /dev/null +++ b/test/test_suite2/enumerations/enum_associated_value.c3t @@ -0,0 +1,51 @@ +// #target: macos-x64 +module test; +import libc; + +enum Foo : uint (int val, char* testme) +{ + A(123, "Number A"), + B(333, "Number B"), +} + +fn void main() +{ + int x = Foo.A.val; + Foo f = Foo.B; + Foo g = Foo.A; + libc::printf("%d (%s) %d (%s)\n", f.val, f.testme, g.val, g.testme); +} + +/* #expect: test.ll + +@.typeid.test.Foo = linkonce constant { i8, i64, i64 } { i8 8, i64 2, i64 2 }, align 8 +@test.Foo.val = linkonce constant [2 x i32] [i32 123, i32 333], align 4 +@.str = private unnamed_addr constant [9 x i8] c"Number A\00", align 1 +@.str.1 = private unnamed_addr constant [9 x i8] c"Number B\00", align 1 +@test.Foo.testme = linkonce constant [2 x ptr] [ptr @.str, ptr @.str.1], align 8 +@.str.2 = private unnamed_addr constant [17 x i8] c"%d (%s) %d (%s)\0A\00", align 1 + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %x = alloca i32, align 4 + %f = alloca i32, align 4 + %g = alloca i32, align 4 + store i32 123, ptr %x, align 4 + store i32 1, ptr %f, align 4 + store i32 0, ptr %g, align 4 + %0 = load i32, ptr %f, align 4 + %1 = getelementptr inbounds [2 x i32], ptr @test.Foo.val, i32 0, i32 %0 + %2 = load i32, ptr %1, align 4 + %3 = load i32, ptr %f, align 4 + %4 = getelementptr inbounds [2 x ptr], ptr @test.Foo.testme, i32 0, i32 %3 + %5 = load ptr, ptr %4, align 8 + %6 = load i32, ptr %g, align 4 + %7 = getelementptr inbounds [2 x i32], ptr @test.Foo.val, i32 0, i32 %6 + %8 = load i32, ptr %7, align 4 + %9 = load i32, ptr %g, align 4 + %10 = getelementptr inbounds [2 x ptr], ptr @test.Foo.testme, i32 0, i32 %9 + %11 = load ptr, ptr %10, align 8 + %12 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %2, ptr %5, i32 %8, ptr %11) + ret void +} diff --git a/test/test_suite2/enumerations/enum_cast.c3t b/test/test_suite2/enumerations/enum_cast.c3t new file mode 100644 index 000000000..6955117e3 --- /dev/null +++ b/test/test_suite2/enumerations/enum_cast.c3t @@ -0,0 +1,99 @@ +// #target: macos-x64 +module test; + +enum MyEnum : char +{ + FOO, + BAR +} + +fn void test2() +{ + char ww = MyEnum.FOO.ordinal; + MyEnum x = MyEnum.BAR; + char zz = x.ordinal; +} + +fn void test() +{ + char b = MyEnum.FOO; + int z = (int)(MyEnum.BAR); + var $foo = (int)(MyEnum.FOO); + var $baz = MyEnum.BAR; + MyEnum x = MyEnum.BAR; + char b2 = x; + int z2 = (int)(x); + float d = (float)(MyEnum.FOO); + bool hello = (bool)(MyEnum.FOO); + var $d = (float)(MyEnum.FOO); + var $hello = (bool)(MyEnum.FOO); + MyEnum! xf = MyEnum.BAR; + float! e = (float)(x); + e = (float)(xf); + +} + +/* #expect: test.ll + +define void @test.test2() #0 { +entry: + %ww = alloca i8, align 1 + %x = alloca i8, align 1 + %zz = alloca i8, align 1 + store i8 0, ptr %ww, align 1 + store i8 1, ptr %x, align 1 + %0 = load i8, ptr %x, align 1 + store i8 %0, ptr %zz, align 1 + ret void +} + +define void @test.test() #0 { +entry: + %b = alloca i8, align 1 + %z = alloca i32, align 4 + %x = alloca i8, align 1 + %b2 = alloca i8, align 1 + %z2 = alloca i32, align 4 + %d = alloca float, align 4 + %hello = alloca i8, align 1 + %xf = alloca i8, align 1 + %xf.f = alloca i64, align 8 + %e = alloca float, align 4 + %e.f = alloca i64, align 8 + store i8 0, ptr %b, align 1 + store i32 1, ptr %z, align 4 + store i8 1, ptr %x, align 1 + %0 = load i8, ptr %x, align 1 + store i8 %0, ptr %b2, align 1 + %1 = load i8, ptr %x, align 1 + %uisiext = zext i8 %1 to i32 + store i32 %uisiext, ptr %z2, align 4 + store float 0.000000e+00, ptr %d, align 4 + store i8 0, ptr %hello, align 1 + store i8 1, ptr %xf, align 1 + store i64 0, ptr %xf.f, align 8 + %2 = load i8, ptr %x, align 1 + %uifp = uitofp i8 %2 to float + store float %uifp, ptr %e, align 4 + store i64 0, ptr %e.f, align 8 + %3 = load i64, ptr %xf.f, align 8 + %not_err = icmp eq i64 %3, 0 + br i1 %not_err, label %after_check, label %error + +error: ; preds = %entry + store i64 %3, ptr %e.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + %4 = load i8, ptr %xf, align 1 + %uifp1 = uitofp i8 %4 to float + store float %uifp1, ptr %e, align 4 + store i64 0, ptr %e.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check, %error + br label %voiderr + +voiderr: ; preds = %after_assign + ret void +} diff --git a/test/test_suite2/enumerations/enum_values.c3t b/test/test_suite2/enumerations/enum_values.c3t new file mode 100644 index 000000000..da5b1aa8b --- /dev/null +++ b/test/test_suite2/enumerations/enum_values.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 + +module test; + +enum Foo +{ + ABC, + BCD +} + +Foo zfok = Foo.values[0]; +Foo[] zw = &&Foo.values; + +fn void test(int x) +{ + Foo zonk = Foo.values[x]; +} + +/* #expect: test.ll + +%"Foo[]" = type { ptr, i64 } + +@test.zfok = local_unnamed_addr global i32 0, align 4 +@.taddr = private global [2 x i32] [i32 0, i32 1], align 4 +@test.zw = local_unnamed_addr global %"Foo[]" { ptr @.taddr, i64 2 }, align 8 + +define void @test.test(i32 %0) #0 { +entry: + %zonk = alloca i32, align 4 + %literal = alloca [2 x i32], align 4 + %1 = getelementptr inbounds [2 x i32], ptr %literal, i64 0, i64 0 + store i32 0, ptr %1, align 4 + %2 = getelementptr inbounds [2 x i32], ptr %literal, i64 0, i64 1 + store i32 1, ptr %2, align 4 + %sisiext = sext i32 %0 to i64 + %3 = getelementptr inbounds [2 x i32], ptr %literal, i64 0, i64 %sisiext + %4 = load i32, ptr %3, align 4 + store i32 %4, ptr %zonk, align 4 + ret void +} diff --git a/test/test_suite2/enumerations/simple_inference.c3t b/test/test_suite2/enumerations/simple_inference.c3t new file mode 100644 index 000000000..018c82eda --- /dev/null +++ b/test/test_suite2/enumerations/simple_inference.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 + +enum HelloEnum +{ + HELLO, + WORLD, + ELLOWORLD, +} +fn void test() +{ + HelloEnum h = WORLD; + h = ELLOWORLD; +} + +/* #expect: simple_inference.ll + +define void @simple_inference.test() #0 { +entry: + %h = alloca i32, align 4 + store i32 1, ptr %h, align 4 + store i32 2, ptr %h, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/anyerr_void.c3t b/test/test_suite2/errors/anyerr_void.c3t new file mode 100644 index 000000000..dcf31daad --- /dev/null +++ b/test/test_suite2/errors/anyerr_void.c3t @@ -0,0 +1,88 @@ +fault MyError +{ + FOO, + BAR +} +fn void! errorThing() +{ + return MyError.BAR!; +} + +fn void! errorThing2() +{ + return; +} + +extern fn void printf(char*, ...); +fn void main() +{ + anyerr z = errorThing(); + printf("Z; %llx\n", (iptr)(z)); + printf("BAR: %llx\n", (iptr)(MyError.BAR)); + printf("FOO: %llx\n", (iptr)(MyError.FOO)); + z = errorThing2(); + printf("Z2: %llx\n", (iptr)(z)); +} + +/* #expect: anyerr_void.ll + +; Function Attrs: nounwind +define i64 @anyerr_void.errorThing() #0 { +entry: + ret i64 ptrtoint (ptr @anyerr_void.MyError.BAR to i64) +} + +; Function Attrs: nounwind +define i64 @anyerr_void.errorThing2() #0 { +entry: + %reterr = alloca i64, align 8 + ret i64 0 +} + +; Function Attrs: nounwind +declare void @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @anyerr_void.main() #0 { +entry: + %z = alloca i64, align 8 + %error_var = alloca i64, align 8 + %error_var1 = alloca i64, align 8 + store i64 0, ptr %error_var, align 8 + %0 = call i64 @anyerr_void.errorThing() + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %0, ptr %error_var, align 8 + br label %noerr_block + +after.errcheck: ; preds = %entry + br label %noerr_block + +noerr_block: ; preds = %after.errcheck, %error + %1 = load i64, ptr %error_var, align 8 + store i64 %1, ptr %z, align 8 + %2 = load i64, ptr %z, align 8 + call void (ptr, ...) @printf(ptr @.str, i64 %2) + call void (ptr, ...) @printf(ptr @.str.1, i64 ptrtoint (ptr @anyerr_void.MyError.BAR to i64)) + call void (ptr, ...) @printf(ptr @.str.2, i64 ptrtoint (ptr @anyerr_void.MyError.FOO to i64)) + store i64 0, ptr %error_var1, align 8 + %3 = call i64 @anyerr_void.errorThing2() + %not_err2 = icmp eq i64 %3, 0 + br i1 %not_err2, label %after.errcheck4, label %error3 + +error3: ; preds = %noerr_block + store i64 %3, ptr %error_var1, align 8 + br label %noerr_block5 + +after.errcheck4: ; preds = %noerr_block + br label %noerr_block5 + +noerr_block5: ; preds = %after.errcheck4, %error3 + %4 = load i64, ptr %error_var1, align 8 + store i64 %4, ptr %z, align 8 + %5 = load i64, ptr %z, align 8 + call void (ptr, ...) @printf(ptr @.str.3, i64 %5) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/bitshift_failable.c3 b/test/test_suite2/errors/bitshift_failable.c3 new file mode 100644 index 000000000..f649501f3 --- /dev/null +++ b/test/test_suite2/errors/bitshift_failable.c3 @@ -0,0 +1,5 @@ +fn void test() +{ + int! x = 0; + int! z = x << 100; // #error: shift exceeds bitsize of 'int' +} \ No newline at end of file diff --git a/test/test_suite2/errors/else_checks.c3t b/test/test_suite2/errors/else_checks.c3t new file mode 100644 index 000000000..9dfcb8bb5 --- /dev/null +++ b/test/test_suite2/errors/else_checks.c3t @@ -0,0 +1,111 @@ +// #target: macos-x64 + +extern fn int! testError(); + +fn void test() +{ + + double x = (testError() + testError()) ?? 100; + double y = (1 << testError()) ?? 100; + double z = testError() >> 1 ?? 100; + double w = testError() * testError() ?? 100; +} + +/* #expect: else_checks.ll + +; Function Attrs: nounwind +declare i64 @testError(ptr) #0 + +; Function Attrs: nounwind +define void @else_checks.test() #0 { +entry: + %x = alloca double, align 8 + %retparam = alloca i32, align 4 + %retparam1 = alloca i32, align 4 + %y = alloca double, align 8 + %retparam4 = alloca i32, align 4 + %z = alloca double, align 8 + %retparam11 = alloca i32, align 4 + %w = alloca double, align 8 + %retparam18 = alloca i32, align 4 + %retparam21 = alloca i32, align 4 + %0 = call i64 @testError(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after.errcheck, label %else_block + +after.errcheck: ; preds = %entry + %1 = load i32, ptr %retparam, align 4 + %2 = call i64 @testError(ptr %retparam1) + %not_err2 = icmp eq i64 %2, 0 + br i1 %not_err2, label %after.errcheck3, label %else_block + +after.errcheck3: ; preds = %after.errcheck + %3 = load i32, ptr %retparam1, align 4 + %add = add i32 %1, %3 + br label %phi_block + +else_block: ; preds = %after.errcheck, %entry + br label %phi_block + +phi_block: ; preds = %else_block, %after.errcheck3 + %val = phi i32 [ %add, %after.errcheck3 ], [ 100, %else_block ] + %sifp = sitofp i32 %val to double + store double %sifp, ptr %x, align 8 + %4 = call i64 @testError(ptr %retparam4) + %not_err5 = icmp eq i64 %4, 0 + br i1 %not_err5, label %after.errcheck6, label %else_block7 + +after.errcheck6: ; preds = %phi_block + %5 = load i32, ptr %retparam4, align 4 + %shl = shl i32 1, %5 + %6 = freeze i32 %shl + br label %phi_block8 + +else_block7: ; preds = %phi_block + br label %phi_block8 + +phi_block8: ; preds = %else_block7, %after.errcheck6 + %val9 = phi i32 [ %6, %after.errcheck6 ], [ 100, %else_block7 ] + %sifp10 = sitofp i32 %val9 to double + store double %sifp10, ptr %y, align 8 + %7 = call i64 @testError(ptr %retparam11) + %not_err12 = icmp eq i64 %7, 0 + br i1 %not_err12, label %after.errcheck13, label %else_block14 + +after.errcheck13: ; preds = %phi_block8 + %8 = load i32, ptr %retparam11, align 4 + %ashr = ashr i32 %8, 1 + %9 = freeze i32 %ashr + br label %phi_block15 + +else_block14: ; preds = %phi_block8 + br label %phi_block15 + +phi_block15: ; preds = %else_block14, %after.errcheck13 + %val16 = phi i32 [ %9, %after.errcheck13 ], [ 100, %else_block14 ] + %sifp17 = sitofp i32 %val16 to double + store double %sifp17, ptr %z, align 8 + %10 = call i64 @testError(ptr %retparam18) + %not_err19 = icmp eq i64 %10, 0 + br i1 %not_err19, label %after.errcheck20, label %else_block24 + +after.errcheck20: ; preds = %phi_block15 + %11 = load i32, ptr %retparam18, align 4 + %12 = call i64 @testError(ptr %retparam21) + %not_err22 = icmp eq i64 %12, 0 + br i1 %not_err22, label %after.errcheck23, label %else_block24 + +after.errcheck23: ; preds = %after.errcheck20 + %13 = load i32, ptr %retparam21, align 4 + %mul = mul i32 %11, %13 + br label %phi_block25 + +else_block24: ; preds = %after.errcheck20, %phi_block15 + br label %phi_block25 + +phi_block25: ; preds = %else_block24, %after.errcheck23 + %val26 = phi i32 [ %mul, %after.errcheck23 ], [ 100, %else_block24 ] + %sifp27 = sitofp i32 %val26 to double + store double %sifp27, ptr %w, align 8 + ret void +} diff --git a/test/test_suite2/errors/error_decl_ok.c3 b/test/test_suite2/errors/error_decl_ok.c3 new file mode 100644 index 000000000..a17338068 --- /dev/null +++ b/test/test_suite2/errors/error_decl_ok.c3 @@ -0,0 +1,19 @@ +module errors; + +fault TheError +{ + A +} + +fault TheError2 +{ + A, + B +} + +fault TheError3 +{ + C, D +} + + diff --git a/test/test_suite2/errors/error_else.c3t b/test/test_suite2/errors/error_else.c3t new file mode 100644 index 000000000..cf6ce3134 --- /dev/null +++ b/test/test_suite2/errors/error_else.c3t @@ -0,0 +1,22 @@ +module foo; + +fault Baz +{ + TEST +} + +module bar; +import foo; + +fn int! abc() +{ + return Baz.TEST!; +} + +module baz; +import foo; + +fn int! abc() +{ + return Baz.TEST!; +} diff --git a/test/test_suite2/errors/error_regression_2.c3t b/test/test_suite2/errors/error_regression_2.c3t new file mode 100644 index 000000000..e32f9245a --- /dev/null +++ b/test/test_suite2/errors/error_regression_2.c3t @@ -0,0 +1,900 @@ +// #target: macos-x64 +module test; +import std; +import libc; + +struct Doc { Head *head; } +struct Head { char[]* title; } + +struct Summary +{ + char[]* title; + bool ok; +} + +fn void Summary.print(Summary *s, CFile out) +{ + // We don't have a native printf in C3 yet, so use libc, + // which is not all that nice for the strings but... + char[] title = s.title ? *s.title : "missing"; + libc::fprintf(out, "Summary({ .title = %.*s, .ok = %s})", (int)title.len, title.ptr, s.ok ? "true" : "false"); +} + +fn bool contains(char[] haystack, char[] needle) +{ + usize len = haystack.len; + usize needle_len = needle.len; + if (len < needle_len) return false; + if (!needle_len) return true; + len -= needle_len - 1; + for (usize i = 0; i < len; i++) + { + if (libc::memcmp(&haystack[i], needle.ptr, needle_len) == 0) + { + return true; + } + } + return false; +} + +macro dupe(value) +{ + $typeof(&value) temp = mem::alloc($sizeof(value)); + if (!temp) return ReadError.OUT_OF_MEMORY!; + *temp = value; + return temp; +} + +fault ReadError +{ + BAD_READ, + OUT_OF_MEMORY +} + +fn Doc! readDoc(char[] url) +{ + if (contains(url, "fail")) return ReadError.BAD_READ!; + if (contains(url, "head-missing")) return { .head = null }; + if (contains(url, "title-missing")) return { dupe(Head { .title = null })? }; + if (contains(url, "title-empty")) return { dupe(Head { .title = dupe((char[])"")? })? }; + // Not particularly elegant due to missing string functions. + int len = libc::snprintf(null, 0, "Title of %.*s", (int)url.len, url.ptr); + char* str = mem::alloc(len + 1); + if (!str) return ReadError.OUT_OF_MEMORY!; + libc::snprintf(str, len + 1, "Title of %.*s", (int)url.len, url.ptr); + return { dupe(Head { .title = dupe(str[..len - 1])? })? }; +} + +fn Summary buildSummary(Doc doc) +{ + return Summary { + .title = doc.head ? doc.head.title : null, + .ok = true, + }; +} + +fn Summary readAndBuildSummary(char[] url) +{ + return buildSummary(readDoc(url)) ?? Summary { .title = null, .ok = false }; + /* + // or + Summary summary = buildSummary(readDoc(url)); + if (catch summary) return Summary { .title = null, .ok = false }; + return summary; + // or + Summary summary = buildSummary(readDoc(url)); + if (try summary) return summary; + return Summary { .title = null, .ok = false }; + */ +} + + +fault TitleResult +{ + TITLE_MISSING +} + +fn bool! isTitleNonEmpty(Doc doc) +{ + if (!doc.head) return TitleResult.TITLE_MISSING!; + char[]* head = doc.head.title; + if (!head) return TitleResult.TITLE_MISSING!; + return (*head).len > 0; +} + + +fn bool! readWhetherTitleNonEmpty(char[] url) +{ + return isTitleNonEmpty(readDoc(url)); +} + +fn char* bool_to_string(bool b) +{ + return b ? "true" : "false"; +} +fn char* nameFromError(anyerr e) +{ + switch (e) + { + case TitleResult.TITLE_MISSING: + return "no title"; + case ReadError.BAD_READ: + return "bad read"; + case ReadError.OUT_OF_MEMORY: + return "out of memory"; + default: + return "unknown error"; + } +} + + +fn void main() +{ + const char[][] URLS = { "good", "title-empty", "title-missing", "head-missing", "fail" }; + foreach (char[] url : URLS) + { + // Yes, it's pretty onerous to print strings for the moment in C3 + libc::printf(`Checking "https://%.*s/":` "\n", (int)url.len, url.ptr); + Summary summary = readAndBuildSummary(url); + libc::printf(" Summary: "); + summary.print(libc::stdout()); + libc::printf("\n"); + char[] title_sure = summary.title ? *summary.title : ""; + libc::printf(" Title: %.*s\n", (int)title_sure.len, title_sure.ptr); + bool! has_title = readWhetherTitleNonEmpty(url); + // This looks a bit less than elegant, but as you see it's mostly due to having to + // use printf here. + libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? nameFromError(catch(has_title)), (has_title ?? false) ? "true" : "false"); + } +} + +/* #expect: test.ll + +define void @test.Summary__print(ptr %0, ptr %1) #0 { +entry: + %title = alloca %"char[]", align 8 + %2 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0 + %3 = load ptr, ptr %2, align 8 + %ptrbool = icmp ne ptr %3, null + br i1 %ptrbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %4 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + %6 = load %"char[]", ptr %5, align 8 + br label %cond.phi + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi %"char[]" [ %6, %cond.lhs ], [ { ptr @.str.26, i64 7 }, %cond.rhs ] + store %"char[]" %val, ptr %title, align 8 + %7 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 1 + %8 = load i64, ptr %7, align 8 + %uisitrunc = trunc i64 %8 to i32 + %9 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 0 + %10 = load ptr, ptr %9, align 8 + %11 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 1 + %12 = load i8, ptr %11, align 8 + %13 = trunc i8 %12 to i1 + %ternary = select i1 %13, ptr @.str.28, ptr @.str.29 + %14 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.27, i32 %uisitrunc, ptr %10, ptr %ternary) + ret void +} + +define zeroext i8 @test.contains(ptr %0, i64 %1, ptr %2, i64 %3) #0 { +entry: + %haystack = alloca %"char[]", align 8 + %needle = alloca %"char[]", align 8 + %len = alloca i64, align 8 + %needle_len = alloca i64, align 8 + %i = alloca i64, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 0 + store ptr %0, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 1 + store i64 %1, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 0 + store ptr %2, ptr %6, align 8 + %7 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 1 + store i64 %3, ptr %7, align 8 + %8 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 1 + %9 = load i64, ptr %8, align 8 + store i64 %9, ptr %len, align 8 + %10 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 1 + %11 = load i64, ptr %10, align 8 + store i64 %11, ptr %needle_len, align 8 + %12 = load i64, ptr %len, align 8 + %13 = load i64, ptr %needle_len, align 8 + %lt = icmp ult i64 %12, %13 + br i1 %lt, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i8 0 + +if.exit: ; preds = %entry + %14 = load i64, ptr %needle_len, align 8 + %not = icmp eq i64 %14, 0 + br i1 %not, label %if.then1, label %if.exit2 + +if.then1: ; preds = %if.exit + ret i8 1 + +if.exit2: ; preds = %if.exit + %15 = load i64, ptr %len, align 8 + %16 = load i64, ptr %needle_len, align 8 + %sub = sub i64 %16, 1 + %sub3 = sub i64 %15, %sub + store i64 %sub3, ptr %len, align 8 + store i64 0, ptr %i, align 8 + br label %loop.cond + +loop.cond: ; preds = %if.exit6, %if.exit2 + %17 = load i64, ptr %i, align 8 + %18 = load i64, ptr %len, align 8 + %lt4 = icmp ult i64 %17, %18 + br i1 %lt4, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %19 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 0 + %20 = load ptr, ptr %19, align 8 + %21 = load i64, ptr %i, align 8 + %ptroffset = getelementptr inbounds i8, ptr %20, i64 %21 + %22 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 0 + %23 = load ptr, ptr %22, align 8 + %24 = load i64, ptr %needle_len, align 8 + %25 = call i32 @memcmp(ptr %ptroffset, ptr %23, i64 %24) + %eq = icmp eq i32 %25, 0 + br i1 %eq, label %if.then5, label %if.exit6 + +if.then5: ; preds = %loop.body + ret i8 1 + +if.exit6: ; preds = %loop.body + %26 = load i64, ptr %i, align 8 + %add = add i64 %26, 1 + store i64 %add, ptr %i, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i8 0 +} + +define i64 @test.readDoc(ptr %0, ptr %1, i64 %2) #0 { +entry: + %url = alloca %"char[]", align 8 + %taddr = alloca %"char[]", align 8 + %taddr5 = alloca %"char[]", align 8 + %reterr = alloca i64, align 8 + %literal = alloca %Doc, align 8 + %taddr12 = alloca %"char[]", align 8 + %reterr16 = alloca i64, align 8 + %literal17 = alloca %Doc, align 8 + %error_var = alloca i64, align 8 + %value = alloca %Head, align 8 + %literal18 = alloca %Head, align 8 + %temp = alloca ptr, align 8 + %taddr24 = alloca %"char[]", align 8 + %reterr28 = alloca i64, align 8 + %literal29 = alloca %Doc, align 8 + %error_var30 = alloca i64, align 8 + %value31 = alloca %Head, align 8 + %literal32 = alloca %Head, align 8 + %error_var33 = alloca i64, align 8 + %value34 = alloca %"char[]", align 8 + %temp35 = alloca ptr, align 8 + %temp41 = alloca ptr, align 8 + %len = alloca i32, align 4 + %str = alloca ptr, align 8 + %reterr54 = alloca i64, align 8 + %literal55 = alloca %Doc, align 8 + %error_var56 = alloca i64, align 8 + %value57 = alloca %Head, align 8 + %literal58 = alloca %Head, align 8 + %error_var59 = alloca i64, align 8 + %value60 = alloca %"char[]", align 8 + %temp61 = alloca ptr, align 8 + %temp67 = alloca ptr, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + store i64 %2, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %6, align 8 + store %"char[]" { ptr @.str, i64 4 }, ptr %taddr, align 8 + %7 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 + %lo1 = load ptr, ptr %7, align 8 + %8 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 + %hi2 = load i64, ptr %8, align 8 + %9 = call i8 @test.contains(ptr %lo, i64 %hi, ptr %lo1, i64 %hi2) + %10 = trunc i8 %9 to i1 + br i1 %10, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @test.ReadError.BAD_READ to i64) + +if.exit: ; preds = %entry + %11 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo3 = load ptr, ptr %11, align 8 + %12 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi4 = load i64, ptr %12, align 8 + store %"char[]" { ptr @.str.1, i64 12 }, ptr %taddr5, align 8 + %13 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 0 + %lo6 = load ptr, ptr %13, align 8 + %14 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 1 + %hi7 = load i64, ptr %14, align 8 + %15 = call i8 @test.contains(ptr %lo3, i64 %hi4, ptr %lo6, i64 %hi7) + %16 = trunc i8 %15 to i1 + br i1 %16, label %if.then8, label %if.exit9 + +if.then8: ; preds = %if.exit + %17 = getelementptr inbounds %Doc, ptr %literal, i32 0, i32 0 + store ptr null, ptr %17, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 8, i1 false) + ret i64 0 + +if.exit9: ; preds = %if.exit + %18 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo10 = load ptr, ptr %18, align 8 + %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi11 = load i64, ptr %19, align 8 + store %"char[]" { ptr @.str.2, i64 13 }, ptr %taddr12, align 8 + %20 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 0 + %lo13 = load ptr, ptr %20, align 8 + %21 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 1 + %hi14 = load i64, ptr %21, align 8 + %22 = call i8 @test.contains(ptr %lo10, i64 %hi11, ptr %lo13, i64 %hi14) + %23 = trunc i8 %22 to i1 + br i1 %23, label %if.then15, label %if.exit21 + +if.then15: ; preds = %if.exit9 + %24 = getelementptr inbounds %Doc, ptr %literal17, i32 0, i32 0 + %25 = getelementptr inbounds %Head, ptr %literal18, i32 0, i32 0 + store ptr null, ptr %25, align 8 + %26 = load %Head, ptr %literal18, align 8 + store %Head %26, ptr %value, align 8 + %27 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) + store ptr %27, ptr %temp, align 8 + %28 = load ptr, ptr %temp, align 8 + %not = icmp eq ptr %28, null + br i1 %not, label %if.then19, label %if.exit20 + +if.then19: ; preds = %if.then15 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var, align 8 + br label %guard_block + +if.exit20: ; preds = %if.then15 + %29 = load ptr, ptr %temp, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %29, ptr align 8 %value, i32 8, i1 false) + br label %noerr_block + +guard_block: ; preds = %if.then19 + %30 = load i64, ptr %error_var, align 8 + ret i64 %30 + +noerr_block: ; preds = %if.exit20 + %31 = load ptr, ptr %temp, align 8 + store ptr %31, ptr %24, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal17, i32 8, i1 false) + ret i64 0 + +if.exit21: ; preds = %if.exit9 + %32 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo22 = load ptr, ptr %32, align 8 + %33 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi23 = load i64, ptr %33, align 8 + store %"char[]" { ptr @.str.3, i64 11 }, ptr %taddr24, align 8 + %34 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 0 + %lo25 = load ptr, ptr %34, align 8 + %35 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 1 + %hi26 = load i64, ptr %35, align 8 + %36 = call i8 @test.contains(ptr %lo22, i64 %hi23, ptr %lo25, i64 %hi26) + %37 = trunc i8 %36 to i1 + br i1 %37, label %if.then27, label %if.exit47 + +if.then27: ; preds = %if.exit21 + %38 = getelementptr inbounds %Doc, ptr %literal29, i32 0, i32 0 + store ptr null, ptr %literal32, align 8 + %39 = getelementptr inbounds %Head, ptr %literal32, i32 0, i32 0 + store %"char[]" { ptr @.str.4, i64 0 }, ptr %value34, align 8 + %40 = call ptr @"std::core::mem.alloc"(i64 16, i64 0) + store ptr %40, ptr %temp35, align 8 + %41 = load ptr, ptr %temp35, align 8 + %not36 = icmp eq ptr %41, null + br i1 %not36, label %if.then37, label %if.exit38 + +if.then37: ; preds = %if.then27 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var33, align 8 + br label %guard_block39 + +if.exit38: ; preds = %if.then27 + %42 = load ptr, ptr %temp35, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %42, ptr align 8 %value34, i32 16, i1 false) + br label %noerr_block40 + +guard_block39: ; preds = %if.then37 + %43 = load i64, ptr %error_var33, align 8 + ret i64 %43 + +noerr_block40: ; preds = %if.exit38 + %44 = load ptr, ptr %temp35, align 8 + store ptr %44, ptr %39, align 8 + %45 = load %Head, ptr %literal32, align 8 + store %Head %45, ptr %value31, align 8 + %46 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) + store ptr %46, ptr %temp41, align 8 + %47 = load ptr, ptr %temp41, align 8 + %not42 = icmp eq ptr %47, null + br i1 %not42, label %if.then43, label %if.exit44 + +if.then43: ; preds = %noerr_block40 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var30, align 8 + br label %guard_block45 + +if.exit44: ; preds = %noerr_block40 + %48 = load ptr, ptr %temp41, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %48, ptr align 8 %value31, i32 8, i1 false) + br label %noerr_block46 + +guard_block45: ; preds = %if.then43 + %49 = load i64, ptr %error_var30, align 8 + ret i64 %49 + +noerr_block46: ; preds = %if.exit44 + %50 = load ptr, ptr %temp41, align 8 + store ptr %50, ptr %38, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal29, i32 8, i1 false) + ret i64 0 + +if.exit47: ; preds = %if.exit21 + %51 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 + %52 = load i64, ptr %51, align 8 + %uisitrunc = trunc i64 %52 to i32 + %53 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 + %54 = load ptr, ptr %53, align 8 + %55 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.5, i32 %uisitrunc, ptr %54) + store i32 %55, ptr %len, align 4 + %56 = load i32, ptr %len, align 4 + %siuiext = sext i32 %56 to i64 + %add = add i64 %siuiext, 1 + %57 = call ptr @"std::core::mem.alloc"(i64 %add, i64 0) + store ptr %57, ptr %str, align 8 + %58 = load ptr, ptr %str, align 8 + %not48 = icmp eq ptr %58, null + br i1 %not48, label %if.then49, label %if.exit50 + +if.then49: ; preds = %if.exit47 + ret i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64) + +if.exit50: ; preds = %if.exit47 + %59 = load ptr, ptr %str, align 8 + %60 = load i32, ptr %len, align 4 + %siuiext51 = sext i32 %60 to i64 + %add52 = add i64 %siuiext51, 1 + %61 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 + %62 = load i64, ptr %61, align 8 + %uisitrunc53 = trunc i64 %62 to i32 + %63 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 + %64 = load ptr, ptr %63, align 8 + %65 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %59, i64 %add52, ptr @.str.6, i32 %uisitrunc53, ptr %64) + %66 = getelementptr inbounds %Doc, ptr %literal55, i32 0, i32 0 + store ptr null, ptr %literal58, align 8 + %67 = getelementptr inbounds %Head, ptr %literal58, i32 0, i32 0 + %68 = load ptr, ptr %str, align 8 + %69 = load i32, ptr %len, align 4 + %sub = sub i32 %69, 1 + %sisiext = sext i32 %sub to i64 + %70 = add i64 %sisiext, 1 + %size = sub i64 %70, 0 + %ptroffset = getelementptr inbounds i8, ptr %68, i64 0 + %71 = insertvalue %"char[]" undef, ptr %ptroffset, 0 + %72 = insertvalue %"char[]" %71, i64 %size, 1 + store %"char[]" %72, ptr %value60, align 8 + %73 = call ptr @"std::core::mem.alloc"(i64 16, i64 0) + store ptr %73, ptr %temp61, align 8 + %74 = load ptr, ptr %temp61, align 8 + %not62 = icmp eq ptr %74, null + br i1 %not62, label %if.then63, label %if.exit64 + +if.then63: ; preds = %if.exit50 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var59, align 8 + br label %guard_block65 + +if.exit64: ; preds = %if.exit50 + %75 = load ptr, ptr %temp61, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %75, ptr align 8 %value60, i32 16, i1 false) + br label %noerr_block66 + +guard_block65: ; preds = %if.then63 + %76 = load i64, ptr %error_var59, align 8 + ret i64 %76 + +noerr_block66: ; preds = %if.exit64 + %77 = load ptr, ptr %temp61, align 8 + store ptr %77, ptr %67, align 8 + %78 = load %Head, ptr %literal58, align 8 + store %Head %78, ptr %value57, align 8 + %79 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) + store ptr %79, ptr %temp67, align 8 + %80 = load ptr, ptr %temp67, align 8 + %not68 = icmp eq ptr %80, null + br i1 %not68, label %if.then69, label %if.exit70 + +if.then69: ; preds = %noerr_block66 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var56, align 8 + br label %guard_block71 + +if.exit70: ; preds = %noerr_block66 + %81 = load ptr, ptr %temp67, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %81, ptr align 8 %value57, i32 8, i1 false) + br label %noerr_block72 + +guard_block71: ; preds = %if.then69 + %82 = load i64, ptr %error_var56, align 8 + ret i64 %82 + +noerr_block72: ; preds = %if.exit70 + %83 = load ptr, ptr %temp67, align 8 + store ptr %83, ptr %66, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal55, i32 8, i1 false) + ret i64 0 +} + +; Function Attrs: nounwind +define { ptr, i8 } @test.buildSummary(ptr %0) #0 { +entry: + %doc = alloca %Doc, align 8 + %literal = alloca %Summary, align 8 + %tempcoerce = alloca { ptr, i8 }, align 8 + %1 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + store ptr %0, ptr %1, align 8 + %2 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 + store ptr null, ptr %2, align 8 + %3 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 + store i8 0, ptr %3, align 8 + %4 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 + %5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %6 = load ptr, ptr %5, align 8 + %ptrbool = icmp ne ptr %6, null + br i1 %ptrbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %7 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + %9 = getelementptr inbounds %Head, ptr %8, i32 0, i32 0 + %10 = load ptr, ptr %9, align 8 + br label %cond.phi + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi ptr [ %10, %cond.lhs ], [ null, %cond.rhs ] + store ptr %val, ptr %4, align 8 + %11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 + store i8 1, ptr %11, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %literal, i32 16, i1 false) + %12 = load { ptr, i8 }, ptr %tempcoerce, align 8 + ret { ptr, i8 } %12 +} + +; Function Attrs: nounwind +define { ptr, i8 } @test.readAndBuildSummary(ptr %0, i64 %1) #0 { +entry: + %url = alloca %"char[]", align 8 + %retparam = alloca %Doc, align 8 + %result = alloca %Summary, align 8 + %literal = alloca %Summary, align 8 + %taddr = alloca %Summary, align 8 + %tempcoerce = alloca { ptr, i8 }, align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %5, align 8 + %6 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %6, 0 + br i1 %not_err, label %after.errcheck, label %else_block + +after.errcheck: ; preds = %entry + %7 = getelementptr inbounds %Doc, ptr %retparam, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + %9 = call { ptr, i8 } @test.buildSummary(ptr %8) + store { ptr, i8 } %9, ptr %result, align 8 + %10 = load %Summary, ptr %result, align 8 + br label %phi_block + +else_block: ; preds = %entry + %11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 + store ptr null, ptr %11, align 8 + %12 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 + store i8 0, ptr %12, align 8 + %13 = load %Summary, ptr %literal, align 8 + br label %phi_block + +phi_block: ; preds = %else_block, %after.errcheck + %val = phi %Summary [ %10, %after.errcheck ], [ %13, %else_block ] + store %Summary %val, ptr %taddr, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %taddr, i32 16, i1 false) + %14 = load { ptr, i8 }, ptr %tempcoerce, align 8 + ret { ptr, i8 } %14 +} + +; Function Attrs: nounwind +define i64 @test.isTitleNonEmpty(ptr %0, ptr %1) #0 { +entry: + %doc = alloca %Doc, align 8 + %head = alloca ptr, align 8 + %reterr = alloca i64, align 8 + %2 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + store ptr %1, ptr %2, align 8 + %3 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %4 = load ptr, ptr %3, align 8 + %not = icmp eq ptr %4, null + br i1 %not, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64) + +if.exit: ; preds = %entry + %5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %6 = load ptr, ptr %5, align 8 + %7 = getelementptr inbounds %Head, ptr %6, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + store ptr %8, ptr %head, align 8 + %9 = load ptr, ptr %head, align 8 + %not1 = icmp eq ptr %9, null + br i1 %not1, label %if.then2, label %if.exit3 + +if.then2: ; preds = %if.exit + ret i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64) + +if.exit3: ; preds = %if.exit + %10 = load ptr, ptr %head, align 8 + %11 = getelementptr inbounds %"char[]", ptr %10, i32 0, i32 1 + %12 = load i64, ptr %11, align 8 + %lt = icmp ult i64 0, %12 + %13 = zext i1 %lt to i8 + store i8 %13, ptr %0, align 1 + ret i64 0 +} + +; Function Attrs: nounwind +define i64 @test.readWhetherTitleNonEmpty(ptr %0, ptr %1, i64 %2) #0 { +entry: + %url = alloca %"char[]", align 8 + %reterr = alloca i64, align 8 + %retparam = alloca i8, align 1 + %retparam1 = alloca %Doc, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + store i64 %2, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %6, align 8 + %7 = call i64 @test.readDoc(ptr %retparam1, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %7, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %7, ptr %reterr, align 8 + br label %err_retblock + +after.errcheck: ; preds = %entry + %8 = getelementptr inbounds %Doc, ptr %retparam1, i32 0, i32 0 + %9 = load ptr, ptr %8, align 8 + %10 = call i64 @test.isTitleNonEmpty(ptr %retparam, ptr %9) + %not_err2 = icmp eq i64 %10, 0 + br i1 %not_err2, label %after.errcheck4, label %error3 + +error3: ; preds = %after.errcheck + store i64 %10, ptr %reterr, align 8 + br label %err_retblock + +after.errcheck4: ; preds = %after.errcheck + %11 = load i8, ptr %retparam, align 1 + store i8 %11, ptr %0, align 1 + ret i64 0 + +err_retblock: ; preds = %error3, %error + %12 = load i64, ptr %reterr, align 8 + ret i64 %12 +} + +; Function Attrs: nounwind +define ptr @test.bool_to_string(i8 zeroext %0) #0 { +entry: + %1 = trunc i8 %0 to i1 + %ternary = select i1 %1, ptr @.str.7, ptr @.str.8 + ret ptr %ternary +} + +; Function Attrs: nounwind +define ptr @test.nameFromError(i64 %0) #0 { +entry: + %switch = alloca i64, align 8 + store i64 %0, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %1 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64), %1 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + ret ptr @.str.9 + +next_if: ; preds = %switch.entry + %eq1 = icmp eq i64 ptrtoint (ptr @test.ReadError.BAD_READ to i64), %1 + br i1 %eq1, label %switch.case2, label %next_if3 + +switch.case2: ; preds = %next_if + ret ptr @.str.10 + +next_if3: ; preds = %next_if + %eq4 = icmp eq i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), %1 + br i1 %eq4, label %switch.case5, label %next_if6 + +switch.case5: ; preds = %next_if3 + ret ptr @.str.11 + +next_if6: ; preds = %next_if3 + br label %switch.default + +switch.default: ; preds = %next_if6 + ret ptr @.str.12 +} + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %URLS = alloca %"char[][]", align 8 + %literal = alloca [5 x %"char[]"], align 16 + %anon = alloca i64, align 8 + %anon1 = alloca %"char[][]", align 8 + %anon2 = alloca i64, align 8 + %url = alloca %"char[]", align 8 + %summary = alloca %Summary, align 8 + %result = alloca %Summary, align 8 + %title_sure = alloca %"char[]", align 8 + %has_title = alloca i8, align 1 + %has_title.f = alloca i64, align 8 + %retparam = alloca i8, align 1 + %0 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 0 + store %"char[]" { ptr @.str.13, i64 4 }, ptr %0, align 8 + %1 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 1 + store %"char[]" { ptr @.str.14, i64 11 }, ptr %1, align 8 + %2 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 2 + store %"char[]" { ptr @.str.15, i64 13 }, ptr %2, align 8 + %3 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 3 + store %"char[]" { ptr @.str.16, i64 12 }, ptr %3, align 8 + %4 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 4 + store %"char[]" { ptr @.str.17, i64 4 }, ptr %4, align 8 + %5 = insertvalue %"char[][]" undef, ptr %literal, 0 + %6 = insertvalue %"char[][]" %5, i64 5, 1 + store %"char[][]" %6, ptr %URLS, align 8 + store i64 0, ptr %anon, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %anon1, ptr align 8 %URLS, i32 16, i1 false) + %7 = getelementptr inbounds %"char[][]", ptr %anon1, i32 0, i32 1 + %8 = load i64, ptr %7, align 8 + store i64 %8, ptr %anon2, align 8 + br label %loop.cond + +loop.cond: ; preds = %phi_block11, %entry + %9 = load i64, ptr %anon, align 8 + %10 = load i64, ptr %anon2, align 8 + %lt = icmp ult i64 %9, %10 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %11 = getelementptr inbounds %"char[][]", ptr %anon1, i32 0, i32 0 + %12 = load ptr, ptr %11, align 8 + %13 = load i64, ptr %anon, align 8 + %ptroffset = getelementptr inbounds %"char[]", ptr %12, i64 %13 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %url, ptr align 8 %ptroffset, i32 16, i1 false) + %14 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 + %15 = load i64, ptr %14, align 8 + %uisitrunc = trunc i64 %15 to i32 + %16 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 + %17 = load ptr, ptr %16, align 8 + %18 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %uisitrunc, ptr %17) + %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %19, align 8 + %20 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %20, align 8 + %21 = call { ptr, i8 } @test.readAndBuildSummary(ptr %lo, i64 %hi) + store { ptr, i8 } %21, ptr %result, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 16, i1 false) + %22 = call i32 (ptr, ...) @printf(ptr @.str.19) + %23 = load ptr, ptr @__stdoutp, align 8 + call void @test.Summary__print(ptr %summary, ptr %23) + %24 = call i32 (ptr, ...) @printf(ptr @.str.20) + %25 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0 + %26 = load ptr, ptr %25, align 8 + %ptrbool = icmp ne ptr %26, null + br i1 %ptrbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %loop.body + %27 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0 + %28 = load ptr, ptr %27, align 8 + %29 = load %"char[]", ptr %28, align 8 + br label %cond.phi + +cond.rhs: ; preds = %loop.body + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi %"char[]" [ %29, %cond.lhs ], [ { ptr @.str.21, i64 0 }, %cond.rhs ] + store %"char[]" %val, ptr %title_sure, align 8 + %30 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 1 + %31 = load i64, ptr %30, align 8 + %uisitrunc3 = trunc i64 %31 to i32 + %32 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 0 + %33 = load ptr, ptr %32, align 8 + %34 = call i32 (ptr, ...) @printf(ptr @.str.22, i32 %uisitrunc3, ptr %33) + %35 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo4 = load ptr, ptr %35, align 8 + %36 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi5 = load i64, ptr %36, align 8 + %37 = call i64 @test.readWhetherTitleNonEmpty(ptr %retparam, ptr %lo4, i64 %hi5) + %not_err = icmp eq i64 %37, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %cond.phi + store i64 %37, ptr %has_title.f, align 8 + br label %after_assign + +after.errcheck: ; preds = %cond.phi + %38 = load i8, ptr %retparam, align 1 + store i8 %38, ptr %has_title, align 1 + store i64 0, ptr %has_title.f, align 8 + br label %after_assign + +after_assign: ; preds = %after.errcheck, %error + %39 = load i64, ptr %has_title.f, align 8 + %not_err6 = icmp eq i64 %39, 0 + br i1 %not_err6, label %after_check, label %else_block + +after_check: ; preds = %after_assign + %40 = load i8, ptr %has_title, align 1 + %41 = call ptr @test.bool_to_string(i8 %40) + br label %phi_block + +else_block: ; preds = %after_assign + %42 = load i64, ptr %has_title.f, align 8 + %43 = call ptr @test.nameFromError(i64 %42) + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val7 = phi ptr [ %41, %after_check ], [ %43, %else_block ] + %44 = load i64, ptr %has_title.f, align 8 + %not_err8 = icmp eq i64 %44, 0 + br i1 %not_err8, label %after_check9, label %else_block10 + +after_check9: ; preds = %phi_block + %45 = load i8, ptr %has_title, align 1 + %46 = trunc i8 %45 to i1 + br label %phi_block11 + +else_block10: ; preds = %phi_block + br label %phi_block11 + +phi_block11: ; preds = %else_block10, %after_check9 + %val12 = phi i1 [ %46, %after_check9 ], [ false, %else_block10 ] + %ternary = select i1 %val12, ptr @.str.24, ptr @.str.25 + %47 = call i32 (ptr, ...) @printf(ptr @.str.23, ptr %val7, ptr %ternary) + %48 = load i64, ptr %anon, align 8 + %add = add i64 %48, 1 + store i64 %add, ptr %anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} diff --git a/test/test_suite2/errors/error_semantic_fails.c3 b/test/test_suite2/errors/error_semantic_fails.c3 new file mode 100644 index 000000000..bfafa510f --- /dev/null +++ b/test/test_suite2/errors/error_semantic_fails.c3 @@ -0,0 +1,5 @@ +fault Repeater +{ + A, + A // #error: This fault value was declared twice. +} diff --git a/test/test_suite2/errors/error_throw.c3 b/test/test_suite2/errors/error_throw.c3 new file mode 100644 index 000000000..dacd9276b --- /dev/null +++ b/test/test_suite2/errors/error_throw.c3 @@ -0,0 +1,12 @@ +module foo; + +fault Blurg +{ + Z +} + +fn void main() +{ + int! i = Blurg.Z!; + int! j = Blurg.Z!; +} \ No newline at end of file diff --git a/test/test_suite2/errors/error_union.c3 b/test/test_suite2/errors/error_union.c3 new file mode 100644 index 000000000..b76a694c9 --- /dev/null +++ b/test/test_suite2/errors/error_union.c3 @@ -0,0 +1,11 @@ +module foo; + +fault Blurg +{ + X, Y, Z +} + +fn void main() +{ + anyerr foo; +} \ No newline at end of file diff --git a/test/test_suite2/errors/failable_inits.c3t b/test/test_suite2/errors/failable_inits.c3t new file mode 100644 index 000000000..e3cb4d26d --- /dev/null +++ b/test/test_suite2/errors/failable_inits.c3t @@ -0,0 +1,113 @@ +// #target: macos-x64 + +module test; +import std::io; +fault Foo +{ + MY_VAL1, + MY_VAL2, +} + +struct Bar +{ + int x; +} + +fn void! test1() +{ + Bar! x = Foo.MY_VAL1!; + Bar y = x?; +} + +fn void! test2() +{ + Bar! x = {}; + Bar y = x?; +} + +fn void main() +{ + test1(); + test2(); +} + +/* #expect: test.ll + +define i64 @test.test1() #0 { +entry: + %x = alloca %Bar, align 4 + %x.f = alloca i64, align 8 + %y = alloca %Bar, align 4 + %error_var = alloca i64, align 8 + %reterr = alloca i64, align 8 + store i64 ptrtoint (ptr @test.Foo.MY_VAL1 to i64), ptr %x.f, align 8 + %0 = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %error + +error: ; preds = %entry + store i64 %0, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %error + %1 = load i64, ptr %error_var, align 8 + ret i64 %1 + +noerr_block: ; preds = %after_check + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 %x, i32 4, i1 false) + ret i64 0 +} + +define i64 @test.test2() #0 { +entry: + %x = alloca %Bar, align 4 + %x.f = alloca i64, align 8 + %y = alloca %Bar, align 4 + %error_var = alloca i64, align 8 + %reterr = alloca i64, align 8 + store i32 0, ptr %x, align 4 + store i64 0, ptr %x.f, align 8 + %0 = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %error + +error: ; preds = %entry + store i64 %0, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %error + %1 = load i64, ptr %error_var, align 8 + ret i64 %1 + +noerr_block: ; preds = %after_check + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 %x, i32 4, i1 false) + ret i64 0 +} + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %0 = call i64 @test.test1() + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after.errcheck, label %voiderr + +after.errcheck: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after.errcheck, %entry + %1 = call i64 @test.test2() + %not_err1 = icmp eq i64 %1, 0 + br i1 %not_err1, label %after.errcheck2, label %voiderr3 + +after.errcheck2: ; preds = %voiderr + br label %voiderr3 + +voiderr3: ; preds = %after.errcheck2, %voiderr + ret void +} diff --git a/test/test_suite2/errors/failable_taddr_and_access.c3t b/test/test_suite2/errors/failable_taddr_and_access.c3t new file mode 100644 index 000000000..ad2d2914a --- /dev/null +++ b/test/test_suite2/errors/failable_taddr_and_access.c3t @@ -0,0 +1,120 @@ +// #target: macos-x64 + +module test; +struct Foo +{ + int x, y; +} + +fault MyErr +{ + FOO +} + +extern fn int printf(char *c, ...); + +fn void main() +{ + int! z = 2; + Foo*! w = &&Foo{ z, 0 }; + printf("%d\n", w.x); + z = MyErr.FOO!; + w = &&Foo{ z, 0 }; + printf("Not visible: %d\n", w.x); +} + +/* #expect: test.ll + +%Foo = type { i32, i32 } + +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@test.MyErr.FOO = linkonce constant i8 1, align 1 +@.typeid.test.MyErr = linkonce constant { i8, i64, [1 x i64] } { i8 9, i64 1, [1 x i64] [i64 ptrtoint (ptr @test.MyErr.FOO to i64)] }, align 8 +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@.str.1 = private unnamed_addr constant [17 x i8] c"Not visible: %d\0A\00", align 1 + +; Function Attrs: nounwind +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %z = alloca i32, align 4 + %z.f = alloca i64, align 8 + %w = alloca ptr, align 8 + %w.f = alloca i64, align 8 + %literal = alloca %Foo, align 4 + %literal4 = alloca %Foo, align 4 + store i32 2, ptr %z, align 4 + store i64 0, ptr %z.f, align 8 + %0 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0 + %1 = load i64, ptr %z.f, align 8 + %not_err = icmp eq i64 %1, 0 + br i1 %not_err, label %after_check, label %error + +error: ; preds = %entry + store i64 %1, ptr %w.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + %2 = load i32, ptr %z, align 4 + store i32 %2, ptr %0, align 4 + %3 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 1 + store i32 0, ptr %3, align 4 + store ptr %literal, ptr %w, align 8 + store i64 0, ptr %w.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check, %error + %4 = load i64, ptr %w.f, align 8 + %not_err1 = icmp eq i64 %4, 0 + br i1 %not_err1, label %after_check2, label %voiderr + +after_check2: ; preds = %after_assign + %5 = load ptr, ptr %w, align 8 + %6 = getelementptr inbounds %Foo, ptr %5, i32 0, i32 0 + %7 = load i32, ptr %6, align 8 + %8 = call i32 (ptr, ...) @printf(ptr @.str, i32 %7) + br label %voiderr + +voiderr: ; preds = %after_check2, %after_assign + store i64 ptrtoint (ptr @test.MyErr.FOO to i64), ptr %z.f, align 8 + br label %voiderr3 + +voiderr3: ; preds = %voiderr + %9 = getelementptr inbounds %Foo, ptr %literal4, i32 0, i32 0 + %10 = load i64, ptr %z.f, align 8 + %not_err5 = icmp eq i64 %10, 0 + br i1 %not_err5, label %after_check7, label %error6 + +error6: ; preds = %voiderr3 + store i64 %10, ptr %w.f, align 8 + br label %after_assign8 + +after_check7: ; preds = %voiderr3 + %11 = load i32, ptr %z, align 4 + store i32 %11, ptr %9, align 4 + %12 = getelementptr inbounds %Foo, ptr %literal4, i32 0, i32 1 + store i32 0, ptr %12, align 4 + store ptr %literal4, ptr %w, align 8 + store i64 0, ptr %w.f, align 8 + br label %after_assign8 + +after_assign8: ; preds = %after_check7, %error6 + br label %voiderr9 + +voiderr9: ; preds = %after_assign8 + %13 = load i64, ptr %w.f, align 8 + %not_err10 = icmp eq i64 %13, 0 + br i1 %not_err10, label %after_check11, label %voiderr12 + +after_check11: ; preds = %voiderr9 + %14 = load ptr, ptr %w, align 8 + %15 = getelementptr inbounds %Foo, ptr %14, i32 0, i32 0 + %16 = load i32, ptr %15, align 8 + %17 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %16) + br label %voiderr12 + +voiderr12: ; preds = %after_check11, %voiderr9 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/failable_untyped_list.c3 b/test/test_suite2/errors/failable_untyped_list.c3 new file mode 100644 index 000000000..3af5e5a82 --- /dev/null +++ b/test/test_suite2/errors/failable_untyped_list.c3 @@ -0,0 +1,24 @@ +module test; +struct Foo +{ + int x, y; +} + +fault MyErr +{ + FOO +} + +extern fn int printf(char *c, ...); + +fn void main() +{ + int! z = 2; + Foo*! w = &&{ z, 0 }; // #error: A failable 'int[2]*!' cannot be converted to 'Foo*' +} + +fn void test() +{ + int! z = 2; + Foo*! w = &&Foo!{ z, 0 }; // #error: please remove the '!' +} \ No newline at end of file diff --git a/test/test_suite2/errors/general_error_regression.c3t b/test/test_suite2/errors/general_error_regression.c3t new file mode 100644 index 000000000..0e20bce28 --- /dev/null +++ b/test/test_suite2/errors/general_error_regression.c3t @@ -0,0 +1,141 @@ +// #target: macos-x64 +module foo; +import std::io; +import libc; +fault Foo +{ + X, + Y, + Z, + W, + W1 + + +} + +fault Foob +{ + X1, + Y2 +} + +define Bar = distinct int; + +enum MyEnum +{ + A, + B +} + +fn void Foo.hello(Foo *f) +{ + io::println("Hello from Foo"); +} + +fn void Bar.hello(Bar *b) +{ + io::println("Hello from Bar"); +} + +fn void MyEnum.hello(MyEnum *myenum) +{ + io::println("Hello from MyEnum"); +} +fn void main() +{ + Foo f = Foo.X; + Foo ef = Foo.Y; + anyerr x = f; + ulong z = (ulong)(x); + libc::printf("1: %p\n", z); + x = ef; + z = (ulong)(x); + libc::printf("2: %p\n", z); + x = Foo.W; + z = (ulong)(x); + libc::printf("21: %p\n", z); + x = Foo.W1; + z = (ulong)(x); + libc::printf("22: %p\n", z); + x = Foob.X1; + z = (ulong)(x); + libc::printf("3: %p\n", z); + x = Foob.Y2; + z = (ulong)(x); + libc::printf("4: %p\n", z); + Bar b; + MyEnum a = MyEnum.A; + f.hello(); + b.hello(); + a.hello(); +} + +/* #expect: foo.ll + +define void @foo.Foo__hello(ptr %0) #0 { +entry: + %1 = call i32 @"std::io.println"(ptr @.str.6) #1 + ret void +} + +define void @foo.Bar__hello(ptr %0) #0 { +entry: + %1 = call i32 @"std::io.println"(ptr @.str.7) #1 + ret void +} + +define void @foo.MyEnum__hello(ptr %0) #0 { +entry: + %1 = call i32 @"std::io.println"(ptr @.str.8) #1 + ret void +} + +define void @foo.main() #0 { +entry: + %f = alloca i64, align 8 + %ef = alloca i64, align 8 + %x = alloca i64, align 8 + %z = alloca i64, align 8 + %b = alloca i32, align 4 + %a = alloca i32, align 4 + store i64 ptrtoint (ptr @foo.Foo.X to i64), ptr %f, align 8 + store i64 ptrtoint (ptr @foo.Foo.Y to i64), ptr %ef, align 8 + %0 = load i64, ptr %f, align 8 + store i64 %0, ptr %x, align 8 + %1 = load i64, ptr %x, align 8 + store i64 %1, ptr %z, align 8 + %2 = load i64, ptr %z, align 8 + %3 = call i32 (ptr, ...) @printf(ptr @.str, i64 %2) + %4 = load i64, ptr %ef, align 8 + store i64 %4, ptr %x, align 8 + %5 = load i64, ptr %x, align 8 + store i64 %5, ptr %z, align 8 + %6 = load i64, ptr %z, align 8 + %7 = call i32 (ptr, ...) @printf(ptr @.str.1, i64 %6) + store i64 ptrtoint (ptr @foo.Foo.W to i64), ptr %x, align 8 + %8 = load i64, ptr %x, align 8 + store i64 %8, ptr %z, align 8 + %9 = load i64, ptr %z, align 8 + %10 = call i32 (ptr, ...) @printf(ptr @.str.2, i64 %9) + store i64 ptrtoint (ptr @foo.Foo.W1 to i64), ptr %x, align 8 + %11 = load i64, ptr %x, align 8 + store i64 %11, ptr %z, align 8 + %12 = load i64, ptr %z, align 8 + %13 = call i32 (ptr, ...) @printf(ptr @.str.3, i64 %12) + store i64 ptrtoint (ptr @foo.Foob.X1 to i64), ptr %x, align 8 + %14 = load i64, ptr %x, align 8 + store i64 %14, ptr %z, align 8 + %15 = load i64, ptr %z, align 8 + %16 = call i32 (ptr, ...) @printf(ptr @.str.4, i64 %15) + store i64 ptrtoint (ptr @foo.Foob.Y2 to i64), ptr %x, align 8 + %17 = load i64, ptr %x, align 8 + store i64 %17, ptr %z, align 8 + %18 = load i64, ptr %z, align 8 + %19 = call i32 (ptr, ...) @printf(ptr @.str.5, i64 %18) + store i32 0, ptr %b, align 4 + store i32 0, ptr %a, align 4 + call void @foo.Foo__hello(ptr %f) + call void @foo.Bar__hello(ptr %b) + call void @foo.MyEnum__hello(ptr %a) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/illegal_use_of_failable.c3 b/test/test_suite2/errors/illegal_use_of_failable.c3 new file mode 100644 index 000000000..b5604fb0a --- /dev/null +++ b/test/test_suite2/errors/illegal_use_of_failable.c3 @@ -0,0 +1,14 @@ +fn void syntaxErrors() +{ + int! i = 0; + while (i + 1) {} // #error: The expression may not be a failable, but was 'int!' + if (i + 1) {} // #error: The expression may not be a failable, but was 'int!' + for (int x = i;;) {} // #error: 'int!' to 'int' + for (int x = 0; x < i + 1;) {} // #error: The expression may not be a failable, but was 'bool!' + for (int x = 0; x < 10; x += i + 1) {} // #error: Cannot assign a failable value to a non-failable + switch (i + 1) // #error: The expression may not be a failable, but was 'int!' + { + default: + i + 1; + } +} diff --git a/test/test_suite2/errors/macro_err.c3t b/test/test_suite2/errors/macro_err.c3t new file mode 100644 index 000000000..1732198de --- /dev/null +++ b/test/test_suite2/errors/macro_err.c3t @@ -0,0 +1,54 @@ +// #target: macos-x64 +module test; +import libc; +fn int! abc() +{ + return 1; +} +macro test() +{ + return abc()?; +} + +fn void main() +{ + libc::printf("%d\n", test() ?? 2); +} + +/* #expect: test.ll + + +define i64 @test.abc(ptr %0) #0 { +entry: + %reterr = alloca i64, align 8 + store i32 1, ptr %0, align 4 + ret i64 0 +} + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %error_var = alloca i64, align 8 + %retparam = alloca i32, align 4 + %0 = call i64 @test.abc(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %0, ptr %error_var, align 8 + br label %guard_block + +after.errcheck: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %error + ret void + +noerr_block: ; preds = %after.errcheck + %1 = load i32, ptr %retparam, align 4 + br label %phi_block + +phi_block: ; preds = %noerr_block + %2 = call i32 (ptr, ...) @printf(ptr @.str, i32 %1) + ret void +} diff --git a/test/test_suite2/errors/macro_err2.c3t b/test/test_suite2/errors/macro_err2.c3t new file mode 100644 index 000000000..a279c57f1 --- /dev/null +++ b/test/test_suite2/errors/macro_err2.c3t @@ -0,0 +1,59 @@ +// #target: macos-x64 +module test; +import libc; +fault Tester { FOO } + +fn int! abc() +{ + return Tester.FOO!; +} +macro test() +{ + defer libc::printf("Test2\n"); + return abc(); +} + +fn void main() +{ + defer libc::printf("Test1\n"); + libc::printf("%d\n", test() ?? 2); +} + +/* #expect: test.ll + +define i64 @test.abc(ptr %0) #0 { +entry: + ret i64 ptrtoint (ptr @test.Tester.FOO to i64) +} + +define void @test.main() #0 { +entry: + %blockret = alloca i32, align 4 + %retparam = alloca i32, align 4 + %0 = call i64 @test.abc(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after.errcheck, label %opt_block_cleanup + +after.errcheck: ; preds = %entry + %1 = call i32 (ptr, ...) @printf(ptr @.str.1) + %2 = load i32, ptr %retparam, align 4 + store i32 %2, ptr %blockret, align 4 + br label %expr_block.exit + +opt_block_cleanup: ; preds = %entry + %3 = call i32 (ptr, ...) @printf(ptr @.str.2) + br label %else_block + +expr_block.exit: ; preds = %after.errcheck + %4 = load i32, ptr %blockret, align 4 + br label %phi_block + +else_block: ; preds = %opt_block_cleanup + br label %phi_block + +phi_block: ; preds = %else_block, %expr_block.exit + %val = phi i32 [ %4, %expr_block.exit ], [ 2, %else_block ] + %5 = call i32 (ptr, ...) @printf(ptr @.str, i32 %val) + %6 = call i32 (ptr, ...) @printf(ptr @.str.3) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/macro_err3.c3t b/test/test_suite2/errors/macro_err3.c3t new file mode 100644 index 000000000..6b6b045ea --- /dev/null +++ b/test/test_suite2/errors/macro_err3.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +import libc; +fault Tester { FOO } + + +macro test() +{ + defer libc::printf("Test2\n"); + return Tester.FOO!; +} + +fn void main() +{ + defer libc::printf("Test1\n"); + libc::printf("%d\n", test() ?? 2); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %blockret = alloca i32, align 4 + br label %opt_block_cleanup + +opt_block_cleanup: ; preds = %entry + %0 = call i32 (ptr, ...) @printf(ptr @.str.2) + br label %else_block + +else_block: ; preds = %opt_block_cleanup + br label %phi_block + +phi_block: ; preds = %else_block + %1 = call i32 (ptr, ...) @printf(ptr @.str, i32 2) + %2 = call i32 (ptr, ...) @printf(ptr @.str.3) + ret void +} diff --git a/test/test_suite2/errors/no_common.c3 b/test/test_suite2/errors/no_common.c3 new file mode 100644 index 000000000..563fdafaa --- /dev/null +++ b/test/test_suite2/errors/no_common.c3 @@ -0,0 +1,13 @@ +fn int! abc() +{ + return 1; +} +macro test() +{ + abc()?; +} + +fn void main() +{ + test() ?? 2; // #error: Cannot find a common type for 'void' and 'int' +} \ No newline at end of file diff --git a/test/test_suite2/errors/or_err_bool.c3t b/test/test_suite2/errors/or_err_bool.c3t new file mode 100644 index 000000000..d516afda8 --- /dev/null +++ b/test/test_suite2/errors/or_err_bool.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 + +module test; + +fn void tester() +{ + bool! x = false; + x ?? true; +} + +/* #expect: test.ll + +define void @test.tester() #0 { +entry: + %x = alloca i8, align 1 + %x.f = alloca i64, align 8 + store i8 0, ptr %x, align 1 + store i64 0, ptr %x.f, align 8 + %0 = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %else_block + +after_check: ; preds = %entry + %1 = load i8, ptr %x, align 1 + %2 = trunc i8 %1 to i1 + br label %phi_block + +else_block: ; preds = %entry + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val = phi i1 [ %2, %after_check ], [ true, %else_block ] + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/precedence_err.c3 b/test/test_suite2/errors/precedence_err.c3 new file mode 100644 index 000000000..0d80271cb --- /dev/null +++ b/test/test_suite2/errors/precedence_err.c3 @@ -0,0 +1,5 @@ + +fn void test() +{ + int x = 3 ^ 5 & 6; // #error: You need to add explicit parentheses to clarify precedence +} diff --git a/test/test_suite2/errors/rethrow.c3t b/test/test_suite2/errors/rethrow.c3t new file mode 100644 index 000000000..6887276a0 --- /dev/null +++ b/test/test_suite2/errors/rethrow.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 + +fn void! test() +{ + int! i; + i?; +} + +// #expect: rethrow.ll + + %i = alloca i32, align 4 + %i.f = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i64 0, ptr %i.f, align 8 + store i32 0, ptr %i, align 4 + %0 = load i64, ptr %i.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %error + +error: ; preds = %entry + store i64 %0, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %error + %1 = load i64, ptr %error_var, align 8 + ret i64 %1 + +noerr_block: ; preds = %after_check + ret i64 0 +} diff --git a/test/test_suite2/errors/rethrow_mingw.c3t b/test/test_suite2/errors/rethrow_mingw.c3t new file mode 100644 index 000000000..529c386d2 --- /dev/null +++ b/test/test_suite2/errors/rethrow_mingw.c3t @@ -0,0 +1,39 @@ +// #target: mingw-x64 + +module rethrow; + +fn void! test() +{ + int! i; + i?; +} + +// #expect: rethrow.ll + +define i64 @rethrow.test() #0 { +entry: + %i = alloca i32, align 4 + %i.f = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i64 0, ptr %i.f, align 8 + store i32 0, ptr %i, align 4 + %0 = load i64, ptr %i.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %error + +error: ; preds = %entry + store i64 %0, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %error + %1 = load i64, ptr %error_var, align 8 + ret i64 %1 + +noerr_block: ; preds = %after_check + ret i64 0 +} + + diff --git a/test/test_suite2/errors/rethrow_no_err.c3 b/test/test_suite2/errors/rethrow_no_err.c3 new file mode 100644 index 000000000..625b268e4 --- /dev/null +++ b/test/test_suite2/errors/rethrow_no_err.c3 @@ -0,0 +1,17 @@ + +fn void test() +{ + test()?; // #error: No failable to rethrow before '?' in the expression, please remove '?' + int i = 0; + if (i?) return; // #error: No failable to rethrow before '?' in the expression, please remove '?' + int! j = 0; + if (j?) return; // #error: This expression implicitly returns with a failable result, but the function + if ((j?)?) return; // #error: This expression implicitly returns with a failable result, but the function +} + +fn void! test2() +{ + int! j = 0; + if (j?) return; + if ((j?)?) return; // #error: No failable to rethrow before '?' in the expression, please remove '?' +} \ No newline at end of file diff --git a/test/test_suite2/errors/simple_static_failable.c3t b/test/test_suite2/errors/simple_static_failable.c3t new file mode 100644 index 000000000..eb805bc39 --- /dev/null +++ b/test/test_suite2/errors/simple_static_failable.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 + +module foo; + +fault Blurg +{ + Y +} + +fn void main() +{ + static int! x = 120; + int! i = Blurg.Y!; +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %i = alloca i32, align 4 + %i.f = alloca i64, align 8 + store i64 ptrtoint (ptr @foo.Blurg.Y to i64), ptr %i.f, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/try_assign.c3t b/test/test_suite2/errors/try_assign.c3t new file mode 100644 index 000000000..30f94cab2 --- /dev/null +++ b/test/test_suite2/errors/try_assign.c3t @@ -0,0 +1,152 @@ +// #target: macos-x64 + +extern fn int! err(); +fault FooErr { QBERT } +extern fn int printf(char* fmt, ...); + +fn void main() +{ + int x = 123; + int! z = 234; + int! w; + int gh = 1; + if (try x = z && try gh = w) + { + printf("Success %d && %d!\n", x, gh); + } + if (try x = z + w) + { + printf("Test\n"); + } + anyerr e; + if (catch e = z) + { + printf("Oh noes!\n"); + } +} + +/* #expect: try_assign.ll + + +define void @try_assign.main() #0 { +entry: + %x = alloca i32, align 4 + %z = alloca i32, align 4 + %z.f = alloca i64, align 8 + %w = alloca i32, align 4 + %w.f = alloca i64, align 8 + %gh = alloca i32, align 4 + %e = alloca i64, align 8 + store i32 123, ptr %x, align 4 + store i32 234, ptr %z, align 4 + store i64 0, ptr %z.f, align 8 + store i64 0, ptr %w.f, align 8 + store i32 0, ptr %w, align 4 + store i32 1, ptr %gh, align 4 + %0 = load i64, ptr %z.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %catch_landing + +after_check: ; preds = %entry + %1 = load i32, ptr %z, align 4 + store i32 %1, ptr %x, align 4 + br label %phi_try_catch + +catch_landing: ; preds = %entry + br label %phi_try_catch + +phi_try_catch: ; preds = %catch_landing, %after_check + %val = phi i1 [ true, %after_check ], [ false, %catch_landing ] + br i1 %val, label %chain_next, label %fail_chain + +chain_next: ; preds = %phi_try_catch + %2 = load i64, ptr %w.f, align 8 + %not_err1 = icmp eq i64 %2, 0 + br i1 %not_err1, label %after_check2, label %catch_landing3 + +after_check2: ; preds = %chain_next + %3 = load i32, ptr %w, align 4 + store i32 %3, ptr %gh, align 4 + br label %phi_try_catch4 + +catch_landing3: ; preds = %chain_next + br label %phi_try_catch4 + +phi_try_catch4: ; preds = %catch_landing3, %after_check2 + %val5 = phi i1 [ true, %after_check2 ], [ false, %catch_landing3 ] + br i1 %val5, label %chain_next6, label %fail_chain + +chain_next6: ; preds = %phi_try_catch4 + br label %end_chain + +fail_chain: ; preds = %phi_try_catch4, %phi_try_catch + br label %end_chain + +end_chain: ; preds = %fail_chain, %chain_next6 + %chain.phi = phi i1 [ true, %chain_next6 ], [ false, %fail_chain ] + br i1 %chain.phi, label %if.then, label %if.exit + +if.then: ; preds = %end_chain + %4 = load i32, ptr %x, align 4 + %5 = load i32, ptr %gh, align 4 + %6 = call i32 (ptr, ...) @printf(ptr @.str, i32 %4, i32 %5) + br label %if.exit + +if.exit: ; preds = %if.then, %end_chain + %7 = load i64, ptr %z.f, align 8 + %not_err7 = icmp eq i64 %7, 0 + br i1 %not_err7, label %after_check8, label %catch_landing11 + +after_check8: ; preds = %if.exit + %8 = load i32, ptr %z, align 4 + %9 = load i64, ptr %w.f, align 8 + %not_err9 = icmp eq i64 %9, 0 + br i1 %not_err9, label %after_check10, label %catch_landing11 + +after_check10: ; preds = %after_check8 + %10 = load i32, ptr %w, align 4 + %add = add i32 %8, %10 + store i32 %add, ptr %x, align 4 + br label %phi_try_catch12 + +catch_landing11: ; preds = %after_check8, %if.exit + br label %phi_try_catch12 + +phi_try_catch12: ; preds = %catch_landing11, %after_check10 + %val13 = phi i1 [ true, %after_check10 ], [ false, %catch_landing11 ] + br i1 %val13, label %if.then14, label %if.exit15 + +if.then14: ; preds = %phi_try_catch12 + %11 = call i32 (ptr, ...) @printf(ptr @.str.1) + br label %if.exit15 + +if.exit15: ; preds = %if.then14, %phi_try_catch12 + store i64 0, ptr %e, align 8 + br label %testblock + +testblock: ; preds = %if.exit15 + %12 = load i64, ptr %z.f, align 8 + %not_err16 = icmp eq i64 %12, 0 + br i1 %not_err16, label %after_check17, label %error + +error: ; preds = %testblock + store i64 %12, ptr %e, align 8 + br label %end_block + +after_check17: ; preds = %testblock + store i64 0, ptr %e, align 8 + br label %end_block + +end_block: ; preds = %after_check17, %error + %13 = load i64, ptr %e, align 8 + %neq = icmp ne i64 %13, 0 + br i1 %neq, label %if.then18, label %if.exit19 + +if.then18: ; preds = %end_block + %14 = call i32 (ptr, ...) @printf(ptr @.str.2) + br label %if.exit19 + +if.exit19: ; preds = %if.then18, %end_block + ret void +} + diff --git a/test/test_suite2/errors/try_catch_if.c3t b/test/test_suite2/errors/try_catch_if.c3t new file mode 100644 index 000000000..23bdcc632 --- /dev/null +++ b/test/test_suite2/errors/try_catch_if.c3t @@ -0,0 +1,99 @@ +// #target: macos-x64 + +fn int hello(int x) +{ + return x + 1; +} + +extern fn int printf(char *c, ...); + +fn int! tester() +{ + printf("In tester\n"); + return 222; +} + +fault Foo +{ + A +} +fn void test1() +{ + int! a = 123; + if (catch err = (a, tester())) + { + printf("Err\n"); + } + else + { + printf("Noerr %d\n", a); + } +} +fn void main() +{ + test1(); +} + +/* #expect: try_catch_if.ll + + +define i64 @try_catch_if.tester(ptr %0) #0 { +entry: + %reterr = alloca i64, align 8 + %1 = call i32 (ptr, ...) @printf(ptr @.str) + store i32 222, ptr %0, align 4 + ret i64 0 +} + +define void @try_catch_if.test1() #0 { +entry: + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %err = alloca i64, align 8 + %retparam = alloca i32, align 4 + store i32 123, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + br label %testblock + +testblock: ; preds = %entry + %0 = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %error + +error: ; preds = %testblock + store i64 %0, ptr %err, align 8 + br label %end_block + +after_check: ; preds = %testblock + br label %testblock1 + +testblock1: ; preds = %after_check + %1 = call i64 @try_catch_if.tester(ptr %retparam) + %not_err2 = icmp eq i64 %1, 0 + br i1 %not_err2, label %after.errcheck, label %error3 + +error3: ; preds = %testblock1 + store i64 %1, ptr %err, align 8 + br label %end_block + +after.errcheck: ; preds = %testblock1 + store i64 0, ptr %err, align 8 + br label %end_block + +end_block: ; preds = %after.errcheck, %error3, %error + %2 = load i64, ptr %err, align 8 + %neq = icmp ne i64 %2, 0 + br i1 %neq, label %if.then, label %if.else + +if.then: ; preds = %end_block + %3 = call i32 (ptr, ...) @printf(ptr @.str.1) + br label %if.exit + +if.else: ; preds = %end_block + %4 = load i32, ptr %a, align 4 + %5 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %4) + br label %if.exit + +if.exit: ; preds = %if.else, %if.then + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/try_catch_unwrapping_while_if.c3 b/test/test_suite2/errors/try_catch_unwrapping_while_if.c3 new file mode 100644 index 000000000..faaf287d7 --- /dev/null +++ b/test/test_suite2/errors/try_catch_unwrapping_while_if.c3 @@ -0,0 +1,98 @@ +extern fn int printf(char* fmt, ...); + +extern fn int! err(); +fault FooErr +{ + X +} +fn void test1() +{ + int! z = 234; + if (try z) + { + int y = z; + z = 12; + z = FooErr.X!; // #error: The variable is unwrapped in this context + } +} + + +fn void test4() +{ + int! z = 234; + int! w = 123; + if (try z && try w && 1) + { + int y = z; + y = w; + } +} + +fn void test5() +{ + int! z = 234; + int! w = 123; + if (try z && try w) + { + int y = z; + } +} +fn void test5b() +{ + int! z = 234; + int! w = 123; + if (try z && try z) // #error: This variable is already unwrapped, so you cannot use 'try' on it again, please remove the 'try'. + { + int y = z; + } +} + +fn void test6() +{ + int! z = 234; + int! w = 123; + while (try z) + { + int y = z; + break; + } +} + +fn void test7() +{ + int! z = 234; + int! w = 123; + if (catch z) + { + } + else + { + int y = z; + } +} + +fn void test8() +{ + int! z = 234; + int! w = 123; + if (catch z) + { + } + else + { + int y = z; + } +} +fn void test9() +{ + int! z = 234; + int! w = 123; + anyerr e; + if (catch e = z) + { + } + else + { + int y = z; + } +} diff --git a/test/test_suite2/errors/try_unwrap_using_assert.c3t b/test/test_suite2/errors/try_unwrap_using_assert.c3t new file mode 100644 index 000000000..9952a9b0c --- /dev/null +++ b/test/test_suite2/errors/try_unwrap_using_assert.c3t @@ -0,0 +1,41 @@ +// #target: macos-x64 +module test; + +extern fn int! maybe(); + +fn int tester(int n) +{ + int! num = maybe(); + assert(try num, "Hello"); + int x = num; + return num; +} + +// #expect: test.ll + +define i32 @test.tester(i32 %0) #0 { +entry: + %num = alloca i32, align 4 + %num.f = alloca i64, align 8 + %retparam = alloca i32, align 4 + %x = alloca i32, align 4 + %1 = call i64 @maybe(ptr %retparam) + %not_err = icmp eq i64 %1, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %1, ptr %num.f, align 8 + br label %after_assign + +after.errcheck: ; preds = %entry + %2 = load i32, ptr %retparam, align 4 + store i32 %2, ptr %num, align 4 + store i64 0, ptr %num.f, align 8 + br label %after_assign + +after_assign: ; preds = %after.errcheck, %error + %3 = load i32, ptr %num, align 4 + store i32 %3, ptr %x, align 4 + %4 = load i32, ptr %num, align 4 + ret i32 %4 +} \ No newline at end of file diff --git a/test/test_suite2/errors/try_with_assign_to_failable.c3 b/test/test_suite2/errors/try_with_assign_to_failable.c3 new file mode 100644 index 000000000..191006004 --- /dev/null +++ b/test/test_suite2/errors/try_with_assign_to_failable.c3 @@ -0,0 +1,6 @@ +fn void test() +{ + int! z; + int! w; + try w = z; // #error: An unwrapping 'try' can only occur as the last element of a conditional, did you want 'try(expr) +} diff --git a/test/test_suite2/errors/try_with_chained_unwrap.c3t b/test/test_suite2/errors/try_with_chained_unwrap.c3t new file mode 100644 index 000000000..8c5078ab3 --- /dev/null +++ b/test/test_suite2/errors/try_with_chained_unwrap.c3t @@ -0,0 +1,58 @@ +// #target: macos-x64 + +extern fn char*! readLine(); +extern fn int! atoi(char*); + +extern fn int printf(char* fmt, ...); + +fn void main() +{ + int val; + if (try val = atoi(readLine())) + { + printf("You typed the number %d\n", val); + return; + } + printf("You didn't type an integer :(\n"); +} + +/* #expect: try_with_chained_unwrap.ll + + +define void @try_with_chained_unwrap.main() #0 { +entry: + %val = alloca i32, align 4 + %retparam = alloca i32, align 4 + %retparam1 = alloca ptr, align 8 + store i32 0, ptr %val, align 4 + %0 = call i64 @readLine(ptr %retparam1) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after.errcheck, label %catch_landing + +after.errcheck: ; preds = %entry + %1 = load ptr, ptr %retparam1, align 8 + %2 = call i64 @atoi(ptr %retparam, ptr %1) + %not_err2 = icmp eq i64 %2, 0 + br i1 %not_err2, label %after.errcheck3, label %catch_landing + +after.errcheck3: ; preds = %after.errcheck + %3 = load i32, ptr %retparam, align 4 + store i32 %3, ptr %val, align 4 + br label %phi_try_catch + +catch_landing: ; preds = %after.errcheck, %entry + br label %phi_try_catch + +phi_try_catch: ; preds = %catch_landing, %after.errcheck3 + %val4 = phi i1 [ true, %after.errcheck3 ], [ false, %catch_landing ] + br i1 %val4, label %if.then, label %if.exit + +if.then: ; preds = %phi_try_catch + %4 = load i32, ptr %val, align 4 + %5 = call i32 (ptr, ...) @printf(ptr @.str, i32 %4) + ret void + +if.exit: ; preds = %phi_try_catch + %6 = call i32 (ptr, ...) @printf(ptr @.str.1) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/errors/try_with_chained_unwrap_errors.c3 b/test/test_suite2/errors/try_with_chained_unwrap_errors.c3 new file mode 100644 index 000000000..272b46519 --- /dev/null +++ b/test/test_suite2/errors/try_with_chained_unwrap_errors.c3 @@ -0,0 +1,93 @@ +fn void test() +{ + int! a; + int b; + if (try int b = a) {} // #error: 'b' would shadow a previous declaration. +} +fn void test2() +{ + int! a; + int b; + if (try b = a) {} + if (try test2 = a) {} // #error: An assignable expression +} + +const int BAZ = 1; + +fn void test3() +{ + + int! a; + int b; + if (try BAZ = a) {} // #error: An assignable expression +} + + +fn void test4() +{ + + int! a; + int b; + if (try b = 1) {} // #error: Expected a failable expression to 'try' here. If it isn't a failable, remove 'try' +} + +fn void test5() +{ + + int! a; + int b; + if (try a = a) {} // #error: This is a failable variable, you should only have non-failable variables on the left side unless you use 'try' without '=' +} + +fn void test6() +{ + + int! a; + int b; + int*! x; + if (try *x = a) {} // #error: This is a failable expression, it can't go on the left hand side of a 'try'. +} + + +fn void test7() +{ + int! a; + int b; + int*! x; + if (try foo::z = a) {} // #error: The variable may not have a path. +} + +fn void test8() +{ + int! a; + int b; + if (b == 0, try b = a && try b = a && b > 0) {} + if (try b = a && try b = a && b > 0) {} + if (try c = a && try c = a) { c++; } +} + +fn void test9() +{ + int! a = 11; + if (try z = a) + { + int g = z++; + } + else + { + z++; // #error: 'z' could not be found, did you spell it right? + } +} + +fn void test10() +{ + int! a = 11; + if (try a) + { + int g = a; + } + else + { + int g = a; // #error: 'int!' to 'int' + } +} \ No newline at end of file diff --git a/test/test_suite2/errors/try_with_unwrap.c3t b/test/test_suite2/errors/try_with_unwrap.c3t new file mode 100644 index 000000000..dd96639cb --- /dev/null +++ b/test/test_suite2/errors/try_with_unwrap.c3t @@ -0,0 +1,84 @@ +// #target: macos-x64 +extern fn char*! readLine(); +extern fn int! atoi(char*); + +extern fn int printf(char* fmt, ...); + +fn void main() +{ + char*! line = readLine(); + if (try line) + { + int! val = atoi(line); + if (try val) + { + printf("You typed the number %d\n", val); + return; + } + } + printf("You didn't type an integer :(\n"); +} + +/* #expect: try_with_unwrap.ll + +define void @try_with_unwrap.main() #0 { +entry: + %line = alloca ptr, align 8 + %line.f = alloca i64, align 8 + %retparam = alloca ptr, align 8 + %val = alloca i32, align 4 + %val.f = alloca i64, align 8 + %retparam1 = alloca i32, align 4 + %0 = call i64 @readLine(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %0, ptr %line.f, align 8 + br label %after_assign + +after.errcheck: ; preds = %entry + %1 = load ptr, ptr %retparam, align 8 + store ptr %1, ptr %line, align 8 + store i64 0, ptr %line.f, align 8 + br label %after_assign + +after_assign: ; preds = %after.errcheck, %error + %load.err = load i64, ptr %line.f, align 8 + %result = icmp eq i64 %load.err, 0 + br i1 %result, label %if.then, label %if.exit9 + +if.then: ; preds = %after_assign + %2 = load ptr, ptr %line, align 8 + %3 = call i64 @atoi(ptr %retparam1, ptr %2) + %not_err2 = icmp eq i64 %3, 0 + br i1 %not_err2, label %after.errcheck4, label %error3 + +error3: ; preds = %if.then + store i64 %3, ptr %val.f, align 8 + br label %after_assign5 + +after.errcheck4: ; preds = %if.then + %4 = load i32, ptr %retparam1, align 4 + store i32 %4, ptr %val, align 4 + store i64 0, ptr %val.f, align 8 + br label %after_assign5 + +after_assign5: ; preds = %after.errcheck4, %error3 + %load.err6 = load i64, ptr %val.f, align 8 + %result7 = icmp eq i64 %load.err6, 0 + br i1 %result7, label %if.then8, label %if.exit + +if.then8: ; preds = %after_assign5 + %5 = load i32, ptr %val, align 4 + %6 = call i32 (ptr, ...) @printf(ptr @.str, i32 %5) + ret void + +if.exit: ; preds = %after_assign5 + br label %if.exit9 + +if.exit9: ; preds = %if.exit, %after_assign + %7 = call i32 (ptr, ...) @printf(ptr @.str.1) + ret void +} + diff --git a/test/test_suite2/errors/try_with_unwrapper.c3t b/test/test_suite2/errors/try_with_unwrapper.c3t new file mode 100644 index 000000000..e5bcca156 --- /dev/null +++ b/test/test_suite2/errors/try_with_unwrapper.c3t @@ -0,0 +1,184 @@ +// #target: macos-x64 + +fn int hello(int x) +{ + return x + 1; +} + +extern fn int printf(char *c, ...); + +fn int! tester() +{ + printf("In tester\n"); + return 222; +} + +fault Foo +{ + A +} +fn void test1() +{ + int! a = 11; + if (try int b = a && try int c = tester()) + { + printf("%d\n", hello(b)); + printf("%d\n", c); + } +} +fn void main() +{ + test1(); +} + +fn void test2() +{ + int! a; + if (try int b = a && hello(b)) + { + hello(b + 1); + } +} + +/* #expect: try_with_unwrapper.ll + + + +; Function Attrs: nounwind +define i32 @try_with_unwrapper.hello(i32 %0) #0 { +entry: + %add = add i32 %0, 1 + ret i32 %add +} + +; Function Attrs: nounwind +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define i64 @try_with_unwrapper.tester(ptr %0) #0 { +entry: + %reterr = alloca i64, align 8 + %1 = call i32 (ptr, ...) @printf(ptr @.str) + store i32 222, ptr %0, align 4 + ret i64 0 +} + +; Function Attrs: nounwind +define void @try_with_unwrapper.test1() #0 { +entry: + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %b = alloca i32, align 4 + %c = alloca i32, align 4 + %retparam = alloca i32, align 4 + store i32 11, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + store i32 0, ptr %b, align 4 + %0 = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %catch_landing + +after_check: ; preds = %entry + %1 = load i32, ptr %a, align 4 + store i32 %1, ptr %b, align 4 + br label %phi_try_catch + +catch_landing: ; preds = %entry + br label %phi_try_catch + +phi_try_catch: ; preds = %catch_landing, %after_check + %val = phi i1 [ true, %after_check ], [ false, %catch_landing ] + br i1 %val, label %chain_next, label %fail_chain + +chain_next: ; preds = %phi_try_catch + store i32 0, ptr %c, align 4 + %2 = call i64 @try_with_unwrapper.tester(ptr %retparam) + %not_err1 = icmp eq i64 %2, 0 + br i1 %not_err1, label %after.errcheck, label %catch_landing2 + +after.errcheck: ; preds = %chain_next + %3 = load i32, ptr %retparam, align 4 + store i32 %3, ptr %c, align 4 + br label %phi_try_catch3 + +catch_landing2: ; preds = %chain_next + br label %phi_try_catch3 + +phi_try_catch3: ; preds = %catch_landing2, %after.errcheck + %val4 = phi i1 [ true, %after.errcheck ], [ false, %catch_landing2 ] + br i1 %val4, label %chain_next5, label %fail_chain + +chain_next5: ; preds = %phi_try_catch3 + br label %end_chain + +fail_chain: ; preds = %phi_try_catch3, %phi_try_catch + br label %end_chain + +end_chain: ; preds = %fail_chain, %chain_next5 + %chain.phi = phi i1 [ true, %chain_next5 ], [ false, %fail_chain ] + br i1 %chain.phi, label %if.then, label %if.exit + +if.then: ; preds = %end_chain + %4 = load i32, ptr %b, align 4 + %5 = call i32 @try_with_unwrapper.hello(i32 %4) + %6 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %5) + %7 = load i32, ptr %c, align 4 + %8 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %7) + br label %if.exit + +if.exit: ; preds = %if.then, %end_chain + ret void +} + + +; Function Attrs: nounwind +define void @try_with_unwrapper.test2() #0 { +entry: + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %b = alloca i32, align 4 + store i64 0, ptr %a.f, align 8 + store i32 0, ptr %a, align 4 + store i32 0, ptr %b, align 4 + %0 = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %catch_landing + +after_check: ; preds = %entry + %1 = load i32, ptr %a, align 4 + store i32 %1, ptr %b, align 4 + br label %phi_try_catch + +catch_landing: ; preds = %entry + br label %phi_try_catch + +phi_try_catch: ; preds = %catch_landing, %after_check + %val = phi i1 [ true, %after_check ], [ false, %catch_landing ] + br i1 %val, label %chain_next, label %fail_chain + +chain_next: ; preds = %phi_try_catch + %2 = load i32, ptr %b, align 4 + %3 = call i32 @try_with_unwrapper.hello(i32 %2) + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %chain_next1, label %fail_chain + +chain_next1: ; preds = %chain_next + br label %end_chain + +fail_chain: ; preds = %chain_next, %phi_try_catch + br label %end_chain + +end_chain: ; preds = %fail_chain, %chain_next1 + %chain.phi = phi i1 [ true, %chain_next1 ], [ false, %fail_chain ] + br i1 %chain.phi, label %if.then, label %if.exit + +if.then: ; preds = %end_chain + %4 = load i32, ptr %b, align 4 + %add = add i32 %4, 1 + %5 = call i32 @try_with_unwrapper.hello(i32 %add) + br label %if.exit + +if.exit: ; preds = %if.then, %end_chain + ret void +} + diff --git a/test/test_suite2/errors/try_with_weird_stuff.c3 b/test/test_suite2/errors/try_with_weird_stuff.c3 new file mode 100644 index 000000000..0561652e0 --- /dev/null +++ b/test/test_suite2/errors/try_with_weird_stuff.c3 @@ -0,0 +1,16 @@ +fn void test1() +{ + + int! a; + int b; + int*! x; + if (try int &a = a) {} // #error: A new variable was expected. +} + +fn void test2() +{ + int! a; + int b; + int*! x; + if (try foo::z = a, b += 1) {} // #error: The 'try' must be placed last, can you change it? +} \ No newline at end of file diff --git a/test/test_suite2/examples/gameoflife.c3 b/test/test_suite2/examples/gameoflife.c3 new file mode 100644 index 000000000..a663e892e --- /dev/null +++ b/test/test_suite2/examples/gameoflife.c3 @@ -0,0 +1,90 @@ +module game_of_life; + +extern fn void printf(char *fmt, ...); +extern fn int atoi(char *val); +extern void *__stdoutp; +extern fn void fflush(void *std); +extern fn int rand(); +extern fn void* malloc(usize size); +extern fn void usleep(int time); + + +struct GameBoard +{ + int h; + int w; + char* world; + char* temp; +} + +fn void GameBoard.show(GameBoard *board) +{ + + printf("\e[H"); + char* current = board.world; + for (int y = 0; y < board.h; y++) + { + for (int x = 0; x < board.w; x++) + { + printf(*current ? "\e[07m \e[m" : " "); + current++; + } + printf("\e[E"); + } + fflush(__stdoutp); +} + +fn void GameBoard.evolve(GameBoard *board) +{ + for (int y = 0; y < board.h; y++) + { + for (int x = 0; x < board.w; x++) + { + int n = 0; + for (int y1 = y - 1; y1 <= y + 1; y1++) + { + for (int x1 = x - 1; x1 <= x + 1; x1++) + { + int actualX = (x1 + board.w) % board.w; + int actualY = (y1 + board.h) % board.h; + if (board.world[actualX + actualY * board.w]) n++; + } + } + if (board.world[x + y * board.w]) n--; + board.temp[x + y * board.w] = (char)(n == 3 || (n == 2 && board.world[x + y * board.w])); + } + } + for (int i = 0; i < board.w * board.h; i++) + { + board.world[i] = board.temp[i]; + } +} + + +fn int main(int c, char** v) +{ + int w = 0; + int h = 0; + if (c > 1) w = atoi(v[1]); + if (c > 2) h = atoi(v[2]); + if (w <= 0) w = 30; + if (h <= 0) h = 30; + + GameBoard board; + board.w = w; + board.h = h; + board.world = malloc(h * w); + board.temp = malloc(h * w); + + for (int i = h * w - 1; i >= 0; i--) + { + board.world[i] = rand() % 10 == 0 ? 1 : 0; + } + for (int j = 0; j < 1000; j++) + { + board.show(); + board.evolve(); + usleep(200000); + } + return 1; +} \ No newline at end of file diff --git a/test/test_suite2/expression_block/expression_block_break.c3 b/test/test_suite2/expression_block/expression_block_break.c3 new file mode 100644 index 000000000..6c558005d --- /dev/null +++ b/test/test_suite2/expression_block/expression_block_break.c3 @@ -0,0 +1,13 @@ +module fe; +import std::io; +extern fn int printf(char *str, ...); + +fn int main() +{ + while(true) + { + return {| break; return 0; |}; // #error: There is no valid target for 'break', did you make a mistake + } + io::println("I didn't return."); + return 0; +} \ No newline at end of file diff --git a/test/test_suite2/expressions/addr_compiles.c3t b/test/test_suite2/expressions/addr_compiles.c3t new file mode 100644 index 000000000..68a7010d5 --- /dev/null +++ b/test/test_suite2/expressions/addr_compiles.c3t @@ -0,0 +1,142 @@ +// #target: macos-x64 + +module test; + +extern fn void printf(char*, ...); + +fn void main() +{ + test(); + test2(); + test3(); +} + +fn void test() +{ + int f = 3; + int* x = &(((f))); + int* h = &&(f++); + printf("x = %d (4), h = %d (3)\n", *x, *h); +} + + +const int XX = 314; +fn void test2() +{ + int* w = &XX; + printf("w = %d (314)\n", *w); +} + +struct Foo +{ + int x; + int y; +} +fn void test3() +{ + Foo h = { 345, 555 }; + int* zx = &h.x; + int* zy = &h.y; + int[3] arr = { 333, 444, 999 }; + printf("zx = %d (345) zy = %d (555)\n", *zx, *zy); + arr[0]--; + arr[1]--; + arr[2]--; + int* d = &arr[2]; + int[]* e = &&arr[1..2]; + printf("d = %d (998) e = %d (443)\n", *d, (*e)[0]); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + call void @test.test() + call void @test.test2() + call void @test.test3() + ret void +} + +; Function Attrs: nounwind +define void @test.test() #0 { +entry: + %f = alloca i32, align 4 + %x = alloca ptr, align 8 + %h = alloca ptr, align 8 + %taddr = alloca i32, align 4 + store i32 3, ptr %f, align 4 + store ptr %f, ptr %x, align 8 + %0 = load i32, ptr %f, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr %f, align 4 + store i32 %0, ptr %taddr, align 4 + store ptr %taddr, ptr %h, align 8 + %1 = load ptr, ptr %x, align 8 + %2 = load i32, ptr %1, align 8 + %3 = load ptr, ptr %h, align 8 + %4 = load i32, ptr %3, align 8 + call void (ptr, ...) @printf(ptr @.str, i32 %2, i32 %4) + ret void +} + +; Function Attrs: nounwind +define void @test.test2() #0 { +entry: + %w = alloca ptr, align 8 + store ptr @test.XX, ptr %w, align 8 + %0 = load ptr, ptr %w, align 8 + %1 = load i32, ptr %0, align 8 + call void (ptr, ...) @printf(ptr @.str.1, i32 %1) + ret void +} + +; Function Attrs: nounwind +define void @test.test3() #0 { +entry: + %h = alloca %Foo, align 4 + %zx = alloca ptr, align 8 + %zy = alloca ptr, align 8 + %arr = alloca [3 x i32], align 4 + %d = alloca ptr, align 8 + %e = alloca ptr, align 8 + %taddr = alloca %"int[]", align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %h, ptr align 4 @.__const, i32 8, i1 false) + %0 = getelementptr inbounds %Foo, ptr %h, i32 0, i32 0 + store ptr %0, ptr %zx, align 8 + %1 = getelementptr inbounds %Foo, ptr %h, i32 0, i32 1 + store ptr %1, ptr %zy, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %arr, ptr align 4 @.__const.2, i32 12, i1 false) + %2 = load ptr, ptr %zx, align 8 + %3 = load i32, ptr %2, align 8 + %4 = load ptr, ptr %zy, align 8 + %5 = load i32, ptr %4, align 8 + call void (ptr, ...) @printf(ptr @.str.3, i32 %3, i32 %5) + %6 = getelementptr inbounds [3 x i32], ptr %arr, i64 0, i64 0 + %7 = load i32, ptr %6, align 4 + %sub = sub i32 %7, 1 + store i32 %sub, ptr %6, align 4 + %8 = getelementptr inbounds [3 x i32], ptr %arr, i64 0, i64 1 + %9 = load i32, ptr %8, align 4 + %sub1 = sub i32 %9, 1 + store i32 %sub1, ptr %8, align 4 + %10 = getelementptr inbounds [3 x i32], ptr %arr, i64 0, i64 2 + %11 = load i32, ptr %10, align 4 + %sub2 = sub i32 %11, 1 + store i32 %sub2, ptr %10, align 4 + %12 = getelementptr inbounds [3 x i32], ptr %arr, i64 0, i64 2 + store ptr %12, ptr %d, align 8 + %13 = getelementptr inbounds [3 x i32], ptr %arr, i64 0, i64 1 + %14 = insertvalue %"int[]" undef, ptr %13, 0 + %15 = insertvalue %"int[]" %14, i64 2, 1 + store %"int[]" %15, ptr %taddr, align 8 + store ptr %taddr, ptr %e, align 8 + %16 = load ptr, ptr %d, align 8 + %17 = load i32, ptr %16, align 8 + %18 = load ptr, ptr %e, align 8 + %19 = getelementptr inbounds %"int[]", ptr %18, i32 0, i32 0 + %20 = load ptr, ptr %19, align 8 + %ptroffset = getelementptr inbounds i32, ptr %20, i64 0 + %21 = load i32, ptr %ptroffset, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %17, i32 %21) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/expressions/addr_of_fails.c3 b/test/test_suite2/expressions/addr_of_fails.c3 new file mode 100644 index 000000000..ec43851b4 --- /dev/null +++ b/test/test_suite2/expressions/addr_of_fails.c3 @@ -0,0 +1,78 @@ +fn void test() +{ + int f; + int* x = &(((f))); + int* h = &&(f++); + int* z = &(f++); // #error: To take the address of a temporary value, use '&&' instead of '&' +} + + +fn void test2() +{ + int f; + var $foo; + int* x = &$foo; // #error: It's not possible to take the address of a compile time value +} + +int he; +macro int hello() +{ + return he; +} + +fn void test3() +{ + int* x = &hello(); // #error: To take the address of a temporary value, use '&&' instead of '&' +} + +fn void test3b() +{ + int* x = &hello; // #error: It is not possible to take the address of a macro. +} + +const X = 2; +const int XX = 3; +fn void test4() +{ + int* w = &XX; +} + +fn void test5() +{ + int* z = &X; // #error: The constant is not typed, either type it or use && to take the reference to a temporary. +} + +struct Foo +{ + int x; + int y; +} + +define heh = he; + +fn void test6() +{ + int* hee = &heh; + Foo h; + int* z = &h.x; + int[3] arr; + int* d = &arr[2]; + int[]* e = &arr[1..2]; // #error: To take the address of a temporary value, use '&&' instead of '&' +} + +define Baz = Foo; +define Bar = distinct int; +fault Err { FOO } +union Un { int x; } +enum MyEnum { BAR } + +fn void test7() +{ + &Baz; // #error: It is not possible to take the address of a type. + &Bar; // #error: It is not possible to take the address of a type. + &Err; // #error: It is not possible to take the address of a type. + &Un; // #error: It is not possible to take the address of a type. + &Err.FOO; // #error: To take the address of a temporary value, use '&&' instead of '&' + &MyEnum; // #error: It is not possible to take the address of a type. + &MyEnum.BAR; // #error: To take the address of a temporary value, use '&&' instead of '&' +} diff --git a/test/test_suite2/expressions/arithmetics.c3 b/test/test_suite2/expressions/arithmetics.c3 new file mode 100644 index 000000000..3644ed17e --- /dev/null +++ b/test/test_suite2/expressions/arithmetics.c3 @@ -0,0 +1,40 @@ +module arithmetics; + +fn void testAdd(int a, int b) +{ + a = a + b; + a += b; + a += 1; +} + +fn void testSub(int a, int b) +{ + a = a - b; + a -= b; + a -= 1; +} + +fn void testMult(int a, int b) +{ + a = a * b; + a *= b; + a *= 1; +} + +fn void testDiv(int a, int b) +{ + a = a / b; + a /= b; + a /= 1; +} + +fn void testAssignment() +{ + ichar x = -3 - 5; + ichar c = -128; +} + +fn char test22() +{ + return 100; +} \ No newline at end of file diff --git a/test/test_suite2/expressions/arithmetics_sema_fail.c3 b/test/test_suite2/expressions/arithmetics_sema_fail.c3 new file mode 100644 index 000000000..ffb6dda03 --- /dev/null +++ b/test/test_suite2/expressions/arithmetics_sema_fail.c3 @@ -0,0 +1,91 @@ + +fn void test7() +{ + double x = 1.2 / 0; // This is ok! NaN +} + +fn void test8() +{ + int y = 0 / 0; // #error: division by zero is not allowed +} + +fn void test9() +{ + int y = 0; + int x = y / 0; // #error: division by zero is not allowed +} + +fn void test10() +{ + 10 = 20; // #error: An assignable expression +} + +fn void test11() +{ + '10' = '20'; // #error: An assignable expression +} + +fn void test12() +{ + true = false; // #error: An assignable expression +} + +fn void test13() +{ + "a" = "b"; // #error: An assignable expression +} + +fn void test14() +{ + 1.2 = 1.3; // #error: An assignable expression +} + +fn void test15() +{ + null = null; // #error: An assignable expression +} + +fn void test16() +{ + int a = 0; + uint b = 2; + ushort c = 3; + a = a + c; + int g = a + b; +} + +fn void test17() +{ + char a = 100 + 300; // #error: '400' is out of range for 'char' +} + +fn void test18() +{ + char b = 100 + 156; // #error: '256' is out of range for 'char' +} + +fn void test19() +{ + ichar b = (-40) - 126; // #error: '-166' is out of range for 'ichar' +} + + + +fn void test20() +{ + ichar d = ((-128 - 10) + 10) - 2; // #error: '-130' is out of range for 'ichar' + ichar c = 100 * 100; // #error: '10000' is out of range for 'ichar' + ichar e = (-138 + 30); + ichar f = -138 + 30; + ichar g = -(128); + check(128); // #error: '128' is out of range for 'ichar' +} + +fn void check(ichar x) {} + + +fn char test22() +{ + return 300; // #error: '300' is out of range for 'char' +} + diff --git a/test/test_suite2/expressions/assign.c3 b/test/test_suite2/expressions/assign.c3 new file mode 100644 index 000000000..046ae8a8d --- /dev/null +++ b/test/test_suite2/expressions/assign.c3 @@ -0,0 +1,5 @@ +fn void test1() +{ + int* p; + *p = 10; +} diff --git a/test/test_suite2/expressions/assignability.c3 b/test/test_suite2/expressions/assignability.c3 new file mode 100644 index 000000000..aeed1330d --- /dev/null +++ b/test/test_suite2/expressions/assignability.c3 @@ -0,0 +1,39 @@ +define Number = int; + +fn void test1() +{ + 10 = 20; // #error: An assignable expression +} + +fn void test2() +{ + "foo" = "bar"; // #error: An assignable expression +} + +fn void test3() +{ + true = false; // #error: An assignable expression +} + +fn void test4() +{ + 'c' = 'd'; // #error: An assignable expression +} + +fn void test5() +{ + 3.14 = 2.14; // #error: An assignable expression +} + +fn void test21() +{ + int a = 0; + int b = 2; + a++ = b++; // #error: An assignable expression +} + +fn void test22() +{ + var $Type = void; + $Type = int; +} \ No newline at end of file diff --git a/test/test_suite2/expressions/assignment_precedence.c3t b/test/test_suite2/expressions/assignment_precedence.c3t new file mode 100644 index 000000000..679360c3a --- /dev/null +++ b/test/test_suite2/expressions/assignment_precedence.c3t @@ -0,0 +1,23 @@ +module prec; + +fn void test() +{ + int i = 1; + int j = 2; + int k = 3; + int l = i = j = k; +} + +// #expect: prec.ll + + %i = alloca i32, align 4 + %j = alloca i32, align 4 + %k = alloca i32, align 4 + %l = alloca i32, align 4 + store i32 1, ptr %i, align 4 + store i32 2, ptr %j, align 4 + store i32 3, ptr %k, align 4 + %0 = load i32, ptr %k, align 4 + store i32 %0, ptr %j, align 4 + store i32 %0, ptr %i, align 4 + store i32 %0, ptr %l, align 4 \ No newline at end of file diff --git a/test/test_suite2/expressions/call_arg_types.c3 b/test/test_suite2/expressions/call_arg_types.c3 new file mode 100644 index 000000000..b260c3732 --- /dev/null +++ b/test/test_suite2/expressions/call_arg_types.c3 @@ -0,0 +1,19 @@ +fn void test2(ichar a) +{} + +fn void test1() +{ + test2(100); + ichar c = 1; + test2(c); + + int a = 1; + test2(a); // #error: 'int' to 'ichar' + test2(100 + a); // #error: 'int' to 'ichar' + + const int X = 120; + test2(X); // #error: 'int' to 'ichar' + + test2(100 + 100); // #error: '200' is out of range for 'ichar' +} + diff --git a/test/test_suite2/expressions/call_inline.c3t b/test/test_suite2/expressions/call_inline.c3t new file mode 100644 index 000000000..57c0df0fe --- /dev/null +++ b/test/test_suite2/expressions/call_inline.c3t @@ -0,0 +1,49 @@ +module inlineme; +import std::io; + +fn void test1() @inline +{ + io::println("Inline!"); +} + +fn void test2() @noinline +{ + io::println("No inline!"); +} + +fn void test3() +{ + io::println("Plain"); +} + +fn void main() +{ + test1() @inline; + test2() @inline; + test3() @inline; + test1() @noinline; + test2() @noinline; + test3() @noinline; + test1(); + test2(); + test3(); +} +// #expect: inlineme.ll + +entry: + call void @inlineme.test1() #2 + call void @inlineme.test2() #2 + call void @inlineme.test3() #2 + call void @inlineme.test1() #3 + call void @inlineme.test2() #3 + call void @inlineme.test3() #3 + call void @inlineme.test1() #2 + call void @inlineme.test2() + call void @inlineme.test3() + ret void +} + +attributes #0 = { nounwind } +attributes #1 = { noinline nounwind } +attributes #2 = { alwaysinline } +attributes #3 = { noinline } \ No newline at end of file diff --git a/test/test_suite2/expressions/casts/cast_const.c3 b/test/test_suite2/expressions/casts/cast_const.c3 new file mode 100644 index 000000000..b109f700c --- /dev/null +++ b/test/test_suite2/expressions/casts/cast_const.c3 @@ -0,0 +1,6 @@ +fn void test1() +{ + ichar a = (ichar)(256 + 1); + ushort b = (ushort)(65536+1); + ichar c = (ushort)(65536+400); // #error: 'ushort' to 'ichar' +} diff --git a/test/test_suite2/expressions/casts/cast_enum_to_various.c3 b/test/test_suite2/expressions/casts/cast_enum_to_various.c3 new file mode 100644 index 000000000..2da5c9758 --- /dev/null +++ b/test/test_suite2/expressions/casts/cast_enum_to_various.c3 @@ -0,0 +1,39 @@ + + + +struct Struct +{ + int x; +} + +enum Enum : uint +{ + A, B +} + +enum EnumB : char +{ + C, D +} + +define Func = fn void(Enum); + +fn void test1(Enum e) +{ + bool a = (bool)(e); + char b = (char)(e); + uint c = (uint)(e); + float d = (float)(e); + uint* f = (uint*)(e); // #error: cast 'Enum' to 'uint*' +} + +fn void test2(Enum e) +{ + Struct* g = (Struct*)(e); // #error: cast 'Enum' to 'Struct*' +} + +fn void test3(Enum e) +{ + EnumB h = (EnumB)(e); // #error: 'Enum' to 'EnumB' is not allowed + Func i = (Func)(e); // #error: cast 'Enum' to 'Func' +} diff --git a/test/test_suite2/expressions/casts/cast_expr.c3t b/test/test_suite2/expressions/casts/cast_expr.c3t new file mode 100644 index 000000000..07b842ad2 --- /dev/null +++ b/test/test_suite2/expressions/casts/cast_expr.c3t @@ -0,0 +1,27 @@ +module cast_expr; + +fn int main(int argc, char** argv) +{ + int a = 10; + + int b = (ichar)(20); + int c = (ichar)(a); + return 0; +} + +// #expect: cast_expr.ll + +define i32 @main + + %a = alloca i32 + %b = alloca i32 + %c = alloca i32 + + store i32 10, ptr %a + store i32 20, ptr %b + %2 = load i32, ptr %a + trunc i32 %2 to i8 + sext i8 %sisitrunc to i32 + store i32 %sisiext, ptr %c + ret i32 0 +} diff --git a/test/test_suite2/expressions/casts/cast_failable.c3 b/test/test_suite2/expressions/casts/cast_failable.c3 new file mode 100644 index 000000000..3fc1b685e --- /dev/null +++ b/test/test_suite2/expressions/casts/cast_failable.c3 @@ -0,0 +1,10 @@ +fault MyErr +{ + FOO +} + +fn void test() +{ + int! x = (int!)(MyErr.FOO!); // #error: Casting to a failable type is not allowed + int! y = MyErr.FOO!; +} \ No newline at end of file diff --git a/test/test_suite2/expressions/casts/cast_func_to_various.c3 b/test/test_suite2/expressions/casts/cast_func_to_various.c3 new file mode 100644 index 000000000..6c747a215 --- /dev/null +++ b/test/test_suite2/expressions/casts/cast_func_to_various.c3 @@ -0,0 +1,45 @@ +struct Struct +{ + int x; +} + +enum Enum : uptr +{ + A, B +} + +define Func = fn void(int); +define FuncOther = fn bool(char*); +define FuncSame = fn void(int); + + +fn void test1(Func arg) +{ + bool a = (bool)(arg); + bool b = arg; +} + +fn void test2(Func arg) +{ + ichar b = (ichar)(arg); // #error: 'Func' (fn void(int)) to 'ichar' +} + +fn void test3(Func arg) +{ + uint c = (uint)(arg); // #error: 'Func' (fn void(int)) to 'uint' +} + +fn void test4(Func arg) +{ + float d = (float)(arg); // #error: 'Func' (fn void(int)) to 'float' +} + +fn void test7(Func arg) +{ + usize g = (usize)(arg); + FuncOther k = (FuncOther)(arg); + FuncSame l = (FuncSame)(arg); + FuncOther ke = arg; // #error: 'Func' (fn void(int)) to 'FuncOther' (fn bool(char*)) + FuncSame fe = arg; + Enum j = (Enum)(arg); // #error: 'Func' (fn void(int)) to 'Enum' +} diff --git a/test/test_suite2/expressions/casts/cast_to_nonscalar.c3 b/test/test_suite2/expressions/casts/cast_to_nonscalar.c3 new file mode 100644 index 000000000..6a43d7a4c --- /dev/null +++ b/test/test_suite2/expressions/casts/cast_to_nonscalar.c3 @@ -0,0 +1,9 @@ +struct Struct +{ + int x; +} + +fn void test1() +{ + int a = (Struct)(200); // #error: 'int' to 'Struct' +} diff --git a/test/test_suite2/expressions/casts/cast_unknown.c3 b/test/test_suite2/expressions/casts/cast_unknown.c3 new file mode 100644 index 000000000..31d34c792 --- /dev/null +++ b/test/test_suite2/expressions/casts/cast_unknown.c3 @@ -0,0 +1,21 @@ +define Number = int; + +fn void test1() +{ + int a = 10; + + int b = (Number)(a); + + int c = (Foo)(a); // #error: 'Foo' could not be found +} + +fn void test2() +{ + int d = (Number)(bar);; // #error: 'bar' could not be found +} + +fn void test3() +{ + int e = (Bar)( // #error: 'Bar' could not be found + faa); // #error: 'faa' could not be found +} diff --git a/test/test_suite2/expressions/casts/explicit_cast.c3 b/test/test_suite2/expressions/casts/explicit_cast.c3 new file mode 100644 index 000000000..4743e41ae --- /dev/null +++ b/test/test_suite2/expressions/casts/explicit_cast.c3 @@ -0,0 +1,15 @@ +define Number8 = char; +define Number32 = int; + +fn void test1() +{ + int a = (ichar)(10); + int b = (ichar)(200); + int c = (int)(200); + ichar d = (int)(200); // #error: 'int' to 'ichar' +} + +fn void test2() +{ + char e = (Number32)(200); // #error: 'Number32' (int) to 'char' +} \ No newline at end of file diff --git a/test/test_suite2/expressions/casts/narrowing.c3 b/test/test_suite2/expressions/casts/narrowing.c3 new file mode 100644 index 000000000..983d0af78 --- /dev/null +++ b/test/test_suite2/expressions/casts/narrowing.c3 @@ -0,0 +1,7 @@ +fn int main() +{ + ushort x; + uint y; + ushort z = x + (ushort)(0x12); + return 0; +} \ No newline at end of file diff --git a/test/test_suite2/expressions/chained_conditional.c3t b/test/test_suite2/expressions/chained_conditional.c3t new file mode 100644 index 000000000..1b476226c --- /dev/null +++ b/test/test_suite2/expressions/chained_conditional.c3t @@ -0,0 +1,69 @@ +module chained; + +fn int foo() +{ + return 1; +} + +fn void test() +{ + int x = foo(); + int y = foo(); + int z = foo(); + if (x > 0 && y > 0 && z > 0) + { + foo(); + } + else + { + x++; + } +} + +// #expect: chained.ll + +entry: + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %z = alloca i32, align 4 + %0 = call i32 @chained.foo() + store i32 %0, ptr %x, align 4 + %1 = call i32 @chained.foo() + store i32 %1, ptr %y, align 4 + %2 = call i32 @chained.foo() + store i32 %2, ptr %z, align 4 + %3 = load i32, ptr %x, align 4 + %gt = icmp sgt i32 %3, 0 + br i1 %gt, label %and.rhs, label %and.phi + +and.rhs: + %4 = load i32, ptr %y, align 4 + %gt1 = icmp sgt i32 %4, 0 + br label %and.phi + +and.phi: + %val = phi i1 [ false, %entry ], [ %gt1, %and.rhs ] + br i1 %val, label %and.rhs2, label %and.phi4 + +and.rhs2: + %5 = load i32, ptr %z, align 4 + %gt3 = icmp sgt i32 %5, 0 + br label %and.phi4 + +and.phi4: + %val5 = phi i1 [ false, %and.phi ], [ %gt3, %and.rhs2 ] + br i1 %val5, label %if.then, label %if.else + +if.then: + %6 = call i32 @chained.foo() + br label %if.exit + +if.else: + %7 = load i32, ptr %x, align 4 + %add = add i32 %7, 1 + store i32 %add, ptr %x, align 4 + br label %if.exit + +if.exit: + ret void +} diff --git a/test/test_suite2/expressions/check_implict_conversion_signed_unsigned.c3t b/test/test_suite2/expressions/check_implict_conversion_signed_unsigned.c3t new file mode 100644 index 000000000..ca0b4200f --- /dev/null +++ b/test/test_suite2/expressions/check_implict_conversion_signed_unsigned.c3t @@ -0,0 +1,23 @@ +module check; + +fn int main() +{ + int a = 0; + ulong b = 3; + b - a; + return 1; +} + +// #expect: check.ll + +entry: + %a = alloca i32, align 4 + %b = alloca i64, align 8 + store i32 0, ptr %a, align 4 + store i64 3, ptr %b, align 8 + %0 = load i64, ptr %b, align 8 + %1 = load i32, ptr %a, align 4 + %sisiext = sext i32 %1 to i64 + %sub = sub i64 %0, %sisiext + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite2/expressions/elvis.c3t b/test/test_suite2/expressions/elvis.c3t new file mode 100644 index 000000000..86a464b46 --- /dev/null +++ b/test/test_suite2/expressions/elvis.c3t @@ -0,0 +1,69 @@ +fn int* elvis(int *x, int *y) +{ + return x ?: y; +} + + +fn int* elvis2(int *x, int *y) +{ + return x ?: (y ?: x); +} + +fn bool elvis3(bool x, bool y) +{ + return x ?: y; +} + + +// #expect: elvis.ll + +define ptr @elvis.elvis(ptr %0, ptr %1) #0 { +entry: + %ptrbool = icmp ne ptr %0, null + br i1 %ptrbool, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %entry + %val = phi ptr [ %0, %entry ], [ %1, %cond.rhs ] + ret ptr %val +} + +define ptr @elvis.elvis2(ptr %0, ptr %1) #0 { +entry: + %ptrbool = icmp ne ptr %0, null + br i1 %ptrbool, label %cond.phi3, label %cond.rhs + +cond.rhs: ; preds = %entry + %ptrbool1 = icmp ne ptr %1, null + br i1 %ptrbool1, label %cond.phi, label %cond.rhs2 + +cond.rhs2: ; preds = %cond.rhs + br label %cond.phi + +cond.phi: ; preds = %cond.rhs2, %cond.rhs + %val = phi ptr [ %1, %cond.rhs ], [ %0, %cond.rhs2 ] + br label %cond.phi3 + +cond.phi3: ; preds = %cond.phi, %entry + %val4 = phi ptr [ %0, %entry ], [ %val, %cond.phi ] + ret ptr %val4 +} + +define zeroext i8 @elvis.elvis3(i8 zeroext %0, i8 zeroext %1) #0 { +entry: + %2 = trunc i8 %0 to i1 + br i1 %2, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %entry + %3 = trunc i8 %1 to i1 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %entry + %val = phi i1 [ %2, %entry ], [ %3, %cond.rhs ] + %4 = zext i1 %val to i8 + ret i8 %4 +} + +attributes #0 = { nounwind } \ No newline at end of file diff --git a/test/test_suite2/expressions/fail_index_usize.c3 b/test/test_suite2/expressions/fail_index_usize.c3 new file mode 100644 index 000000000..911ebd3e0 --- /dev/null +++ b/test/test_suite2/expressions/fail_index_usize.c3 @@ -0,0 +1,5 @@ +fn void test(int* array, usize n) +{ + array[n] = 33; + n[array] = 33; // #error: Cannot index +} diff --git a/test/test_suite2/expressions/folding_ptr.c3t b/test/test_suite2/expressions/folding_ptr.c3t new file mode 100644 index 000000000..cb56076a4 --- /dev/null +++ b/test/test_suite2/expressions/folding_ptr.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module test; +struct Test +{ + int x; +} + +extern Test *cfun; + +fn int f() +{ + if (!(cfun + 0)) return 0; + return cfun.x; +} + + +/* #expect: test.ll + +define i32 @test.f() #0 { +entry: + %0 = load ptr, ptr @cfun, align 8 + %ptroffset = getelementptr %Test, ptr %0, i64 0 + %not = icmp eq ptr %ptroffset, null + br i1 %not, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i32 0 + +if.exit: ; preds = %entry + %1 = load ptr, ptr @cfun, align 8 + %2 = getelementptr inbounds %Test, ptr %1, i32 0, i32 0 + %3 = load i32, ptr %2, align 8 + ret i32 %3 +} diff --git a/test/test_suite2/expressions/incdec.c3t b/test/test_suite2/expressions/incdec.c3t new file mode 100644 index 000000000..cb4404e02 --- /dev/null +++ b/test/test_suite2/expressions/incdec.c3t @@ -0,0 +1,44 @@ +fn void test(int* foo) +{ + foo++; + foo--; + int y = 10; + y++; + y--; + float z = 2.0; + z++; + ++z; + z--; +} + +/* #expect: incdec.ll + + + %foo = alloca ptr, align 8 + %y = alloca i32, align 4 + %z = alloca float, align 4 + store ptr %0, ptr %foo, align 8 + %1 = load ptr, ptr %foo, align 8 + %ptroffset = getelementptr i32, ptr %1, i8 1 + store ptr %ptroffset, ptr %foo, align 8 + %2 = load ptr, ptr %foo, align 8 + %ptroffset1 = getelementptr i32, ptr %2, i8 -1 + store ptr %ptroffset1, ptr %foo, align 8 + store i32 10, ptr %y, align 4 + %3 = load i32, ptr %y, align 4 + %add = add i32 %3, 1 + store i32 %add, ptr %y, align 4 + %4 = load i32, ptr %y, align 4 + %sub = sub i32 %4, 1 + store i32 %sub, ptr %y, align 4 + store float 2.000000e+00, ptr %z, align 4 + %5 = load float, ptr %z, align 4 + %fincdec = fadd float %5, 1.000000e+00 + store float %fincdec, ptr %z, align 4 + %6 = load float, ptr %z, align 4 + %fincdec2 = fadd float %6, 1.000000e+00 + store float %fincdec2, ptr %z, align 4 + %7 = load float, ptr %z, align 4 + %fincdec3 = fadd float %7, -1.000000e+00 + store float %fincdec3, ptr %z, align 4 + ret void diff --git a/test/test_suite2/expressions/negate_int.c3 b/test/test_suite2/expressions/negate_int.c3 new file mode 100644 index 000000000..258fbbd1b --- /dev/null +++ b/test/test_suite2/expressions/negate_int.c3 @@ -0,0 +1,41 @@ +fn void test1() +{ + short! a = 1; + try(-a); + short b = -a; // #error: 'int!' cannot be converted to 'short' +} + +fn void test2() +{ + int! a = 1; + try(-a); + int b = -a; // #error: 'int!' to 'int' +} + +fn void test3() +{ + long! a = 1; + try(-a); + long b = -a; // #error: 'long!' to 'long' +} + +fn void test4() +{ + short! a = 1; + try(~a); + short b = ~a; // #error: 'short!' to 'short' +} + +fn void test5() +{ + int! a = 1; + try(~a); + int b = ~a; // #error: 'int!' to 'int' +} + +fn void test6() +{ + long! a = 1; + try(~a); + long b = ~a; // #error: 'long!' to 'long' +} diff --git a/test/test_suite2/expressions/no_valid_conversion_minus.c3 b/test/test_suite2/expressions/no_valid_conversion_minus.c3 new file mode 100644 index 000000000..68ad6a1c1 --- /dev/null +++ b/test/test_suite2/expressions/no_valid_conversion_minus.c3 @@ -0,0 +1,10 @@ +struct Foo +{ int j; } + +fn int main() +{ + int a = 0; + Foo f; + f - a; // #error: The subtraction 'Foo' - 'int' is not possible + return 1; +} \ No newline at end of file diff --git a/test/test_suite2/expressions/parsed_numbers.c3t b/test/test_suite2/expressions/parsed_numbers.c3t new file mode 100644 index 000000000..ce2809a64 --- /dev/null +++ b/test/test_suite2/expressions/parsed_numbers.c3t @@ -0,0 +1,13 @@ +module numbers; + +double a = 0x1.1p+1; +double b = -12.3e-12; +double c = 0x1.1p-1; +double d = 12.3e+12; + +// #expect: numbers.ll + +@numbers.a = local_unnamed_addr global double 2.125000e+00, align 8 +@numbers.b = local_unnamed_addr global double -1.230000e-11, align 8 +@numbers.c = local_unnamed_addr global double 5.312500e-01, align 8 +@numbers.d = local_unnamed_addr global double 1.230000e+13, align 8 \ No newline at end of file diff --git a/test/test_suite2/expressions/pointer_access.c3t b/test/test_suite2/expressions/pointer_access.c3t new file mode 100644 index 000000000..680e20d9b --- /dev/null +++ b/test/test_suite2/expressions/pointer_access.c3t @@ -0,0 +1,104 @@ +// #target: macos-x64 +extern fn void printf(char* c, ...); + +struct ExtraSimple +{ + int a; + int b; + struct c + { + double e; + double f0; + double f1; + double f; + double j; + } + struct + { + int r; + int s; + } + union + { + double o0; + int o1; + } + int g; +} + + +fn void testSimple() +{ + ExtraSimple a = { .c.j = 3.3 }; + a.c.j = 3.4; + printf("a = %d, c.e = %f, c.f = %f, c.j = %f, g = %d, o0 = %f, r = %d, s = %d\n", a.a, a.c.e, a.c.f, a.c.j, a.g, a.o0, a.r, a.s); +} + +// TODO these may be wrong. +/* #expect: pointer_access.ll + +%ExtraSimple = type { i32, i32, %c, %anon, %anon.0, i32 } +%c = type { double, double, double, double, double } +%anon = type { i32, i32 } +%anon.0 = type { double } + +@.typeid.pointer_access.c = linkonce constant { i8, i64 } { i8 10, i64 5 }, align 8 +@.typeid.pointer_access.anon = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.typeid.pointer_access.anon.1 = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.pointer_access.ExtraSimple = linkonce constant { i8, i64 } { i8 10, i64 6 }, align 8 +@.str = private unnamed_addr constant [71 x i8] c"a = %d, c.e = %f, c.f = %f, c.j = %f, g = %d, o0 = %f, r = %d, s = %d\0A\00", align 1 + +define void @pointer_access.testSimple() #0 { +entry: + %a = alloca %ExtraSimple, align 8 + %0 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 0 + store i32 0, ptr %0, align 8 + %1 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 1 + store i32 0, ptr %1, align 4 + %2 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 2 + %3 = getelementptr inbounds %c, ptr %2, i32 0, i32 0 + store double 0.000000e+00, ptr %3, align 8 + %4 = getelementptr inbounds %c, ptr %2, i32 0, i32 1 + store double 0.000000e+00, ptr %4, align 8 + %5 = getelementptr inbounds %c, ptr %2, i32 0, i32 2 + store double 0.000000e+00, ptr %5, align 8 + %6 = getelementptr inbounds %c, ptr %2, i32 0, i32 3 + store double 0.000000e+00, ptr %6, align 8 + %7 = getelementptr inbounds %c, ptr %2, i32 0, i32 4 + store double 3.300000e+00, ptr %7, align 8 + %8 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 3 + %9 = getelementptr inbounds %anon, ptr %8, i32 0, i32 0 + store i32 0, ptr %9, align 8 + %10 = getelementptr inbounds %anon, ptr %8, i32 0, i32 1 + store i32 0, ptr %10, align 4 + %11 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 4 + call void @llvm.memset.p0.i64(ptr align 8 %11, i8 0, i64 8, i1 false) + %12 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 5 + store i32 0, ptr %12, align 8 + %13 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 2 + %14 = getelementptr inbounds %c, ptr %13, i32 0, i32 4 + store double 3.400000e+00, ptr %14, align 8 + %15 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 0 + %16 = load i32, ptr %15, align 8 + %17 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 2 + %18 = getelementptr inbounds %c, ptr %17, i32 0, i32 0 + %19 = load double, ptr %18, align 8 + %20 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 2 + %21 = getelementptr inbounds %c, ptr %20, i32 0, i32 3 + %22 = load double, ptr %21, align 8 + %23 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 2 + %24 = getelementptr inbounds %c, ptr %23, i32 0, i32 4 + %25 = load double, ptr %24, align 8 + %26 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 5 + %27 = load i32, ptr %26, align 8 + %28 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 4 + %29 = load double, ptr %28, align 8 + %30 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 3 + %31 = getelementptr inbounds %anon, ptr %30, i32 0, i32 0 + %32 = load i32, ptr %31, align 8 + %33 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 3 + %34 = getelementptr inbounds %anon, ptr %33, i32 0, i32 1 + %35 = load i32, ptr %34, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %16, double %19, double %22, double %25, i32 %27, double %29, i32 %32, i32 %35) + ret void +} diff --git a/test/test_suite2/expressions/pointer_arith.c3 b/test/test_suite2/expressions/pointer_arith.c3 new file mode 100644 index 000000000..2338aa493 --- /dev/null +++ b/test/test_suite2/expressions/pointer_arith.c3 @@ -0,0 +1,18 @@ +fn void test1(ichar* cp) +{ + int a = 10; + + ichar* cp2 = cp - 10; + ichar* cp3 = cp + 10; + cp2 -= 10; + cp2 -= a; + cp3 += 10; + cp3 += a; + ichar* cp4 = cp - a; + cp2 - cp3; +} +fn void test2(ichar* cp) +{ + cp + 1; + cp * 1.0; // #error: 'ichar*' by 'double' +} \ No newline at end of file diff --git a/test/test_suite2/expressions/pointer_conv_error.c3 b/test/test_suite2/expressions/pointer_conv_error.c3 new file mode 100644 index 000000000..40e59f04e --- /dev/null +++ b/test/test_suite2/expressions/pointer_conv_error.c3 @@ -0,0 +1,18 @@ +fn void test1() +{ + int myInt = 1; + int* p1 = myInt; // #error: 'int' into 'int*' +} + +fn void test2() +{ + uint myUInt = 1; + int* p2 = myUInt; // #error: 'uint' into 'int*' +} + +fn void test3() +{ + uint myUInt = 1; + int* p2 = (int*)(myUInt); // #error: 'uint' to 'int*' +} + diff --git a/test/test_suite2/expressions/pointer_to_bool.c3 b/test/test_suite2/expressions/pointer_to_bool.c3 new file mode 100644 index 000000000..fcdf1292d --- /dev/null +++ b/test/test_suite2/expressions/pointer_to_bool.c3 @@ -0,0 +1,9 @@ +struct Struct +{ + char* ptr; +} + +fn void test1(Struct* s) +{ + if (s.ptr) {} +} \ No newline at end of file diff --git a/test/test_suite2/expressions/rvalues.c3 b/test/test_suite2/expressions/rvalues.c3 new file mode 100644 index 000000000..fd4d9c237 --- /dev/null +++ b/test/test_suite2/expressions/rvalues.c3 @@ -0,0 +1,16 @@ +macro void hello($bar) +{ + $bar; +} +const FOO = 1 + 2; +fn void test() +{ + var $Foo = int; + var $Bar = $Foo; + $Bar x; + hello(1); + var $foo = 1; + $foo; + FOO; +} + diff --git a/test/test_suite2/expressions/simple_float_sub_neg.c3t b/test/test_suite2/expressions/simple_float_sub_neg.c3t new file mode 100644 index 000000000..79cb304ab --- /dev/null +++ b/test/test_suite2/expressions/simple_float_sub_neg.c3t @@ -0,0 +1,17 @@ +module simple_float_sub_neg; + +fn double test(double a, double b, double c, double d) +{ + return -(a-b) - (c-d); +} + +// #expect: simple_float_sub_neg.ll + +define double @simple_float_sub_neg.test(double %0, double %1, double %2, double %3) #0 { +entry: + %fsub = fsub double %0, %1 + %fneg = fneg double %fsub + %fsub1 = fsub double %2, %3 + %fsub2 = fsub double %fneg, %fsub1 + ret double %fsub2 +} diff --git a/test/test_suite2/expressions/strings.c3t b/test/test_suite2/expressions/strings.c3t new file mode 100644 index 000000000..e73306b83 --- /dev/null +++ b/test/test_suite2/expressions/strings.c3t @@ -0,0 +1,10 @@ +module test; + +fn char* foo() +{ + return "*** Word \"%s\" on line %d is not"; +} + +// #expect: test.ll + +@.str = private unnamed_addr constant [32 x i8] c"*** Word \22%s\22 on line %d is not\00" \ No newline at end of file diff --git a/test/test_suite2/expressions/ternary_bool.c3t b/test/test_suite2/expressions/ternary_bool.c3t new file mode 100644 index 000000000..1cc7e274d --- /dev/null +++ b/test/test_suite2/expressions/ternary_bool.c3t @@ -0,0 +1,110 @@ +// #target: macos-x64 + +extern fn void printf(char *, ...); + +fn void main() +{ + + bool b = true; + bool* c = &b; + if (*c ? *c : *c) printf("Woa!\n"); + if (b ? b : b) printf("Woa!\n"); + if (*c ?: *c) printf("Woa!\n"); + if (b ?: b) printf("Woa!\n"); +} + +/* #expect: ternary_bool.ll + +define void @ternary_bool.main() #0 { +entry: + %b = alloca i8, align 1 + %c = alloca ptr, align 8 + store i8 1, ptr %b, align 1 + store ptr %b, ptr %c, align 8 + %0 = load ptr, ptr %c, align 8 + %1 = load i8, ptr %0, align 8 + %2 = trunc i8 %1 to i1 + br i1 %2, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %3 = load ptr, ptr %c, align 8 + %4 = load i8, ptr %3, align 8 + br label %cond.phi + +cond.rhs: ; preds = %entry + %5 = load ptr, ptr %c, align 8 + %6 = load i8, ptr %5, align 8 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi i8 [ %4, %cond.lhs ], [ %6, %cond.rhs ] + %7 = trunc i8 %val to i1 + br i1 %7, label %if.then, label %if.exit + +if.then: ; preds = %cond.phi + call void (ptr, ...) @printf(ptr @.str) + br label %if.exit + +if.exit: ; preds = %if.then, %cond.phi + %8 = load i8, ptr %b, align 1 + %9 = trunc i8 %8 to i1 + br i1 %9, label %cond.lhs1, label %cond.rhs2 + +cond.lhs1: ; preds = %if.exit + %10 = load i8, ptr %b, align 1 + br label %cond.phi3 + +cond.rhs2: ; preds = %if.exit + %11 = load i8, ptr %b, align 1 + br label %cond.phi3 + +cond.phi3: ; preds = %cond.rhs2, %cond.lhs1 + %val4 = phi i8 [ %10, %cond.lhs1 ], [ %11, %cond.rhs2 ] + %12 = trunc i8 %val4 to i1 + br i1 %12, label %if.then5, label %if.exit6 + +if.then5: ; preds = %cond.phi3 + call void (ptr, ...) @printf(ptr @.str.1) + br label %if.exit6 + +if.exit6: ; preds = %if.then5, %cond.phi3 + %13 = load ptr, ptr %c, align 8 + %14 = load i8, ptr %13, align 8 + %15 = trunc i8 %14 to i1 + br i1 %15, label %cond.phi8, label %cond.rhs7 + +cond.rhs7: ; preds = %if.exit6 + %16 = load ptr, ptr %c, align 8 + %17 = load i8, ptr %16, align 8 + %18 = trunc i8 %17 to i1 + br label %cond.phi8 + +cond.phi8: ; preds = %cond.rhs7, %if.exit6 + %val9 = phi i1 [ %15, %if.exit6 ], [ %18, %cond.rhs7 ] + br i1 %val9, label %if.then10, label %if.exit11 + +if.then10: ; preds = %cond.phi8 + call void (ptr, ...) @printf(ptr @.str.2) + br label %if.exit11 + +if.exit11: ; preds = %if.then10, %cond.phi8 + %19 = load i8, ptr %b, align 1 + %20 = trunc i8 %19 to i1 + br i1 %20, label %cond.phi13, label %cond.rhs12 + +cond.rhs12: ; preds = %if.exit11 + %21 = load i8, ptr %b, align 1 + %22 = trunc i8 %21 to i1 + br label %cond.phi13 + +cond.phi13: ; preds = %cond.rhs12, %if.exit11 + %val14 = phi i1 [ %20, %if.exit11 ], [ %22, %cond.rhs12 ] + br i1 %val14, label %if.then15, label %if.exit16 + +if.then15: ; preds = %cond.phi13 + call void (ptr, ...) @printf(ptr @.str.3) + br label %if.exit16 + +if.exit16: ; preds = %if.then15, %cond.phi13 + ret void +} diff --git a/test/test_suite2/expressions/ternary_no_ident.c3 b/test/test_suite2/expressions/ternary_no_ident.c3 new file mode 100644 index 000000000..dbd2e7457 --- /dev/null +++ b/test/test_suite2/expressions/ternary_no_ident.c3 @@ -0,0 +1,14 @@ +fn void test1() +{ + int a = (i ? 1 : 1); // #error: 'i' could not be found, did you spell it right +} + +fn void test2() +{ + int a = (1 ? i : 2); // #error: 'i' could not be found, did you spell it right +} + +fn void test3() +{ + int a = (1 ? 2 : i); // #error: 'i' could not be found, did you spell it right +} diff --git a/test/test_suite2/expressions/unsafe_comparisons.c3 b/test/test_suite2/expressions/unsafe_comparisons.c3 new file mode 100644 index 000000000..013b889e9 --- /dev/null +++ b/test/test_suite2/expressions/unsafe_comparisons.c3 @@ -0,0 +1,41 @@ +module test; + +fn bool test1(uint x) +{ + return x < 0; // #error: Comparing 'unsigned expression < 0' can never be true +} + +fn bool test2(uint x) +{ + return x <= 0; // #error: 'unsigned expression <= 0' is the same as expr == 0 +} + +fn bool test3(uint x) +{ + return x == -1; // #error: Comparing an unsigned value with a negative constant +} + +fn bool test4(uint x) +{ + return 0 > x ; // #error: '0 > unsigned expression' can never be true +} + +fn bool test5(uint x) +{ + return 0 >= x; // #error: '0 >= unsigned expression' is the same as 0 == expr +} + +fn bool test6(uint x) +{ + return -1 == x; // #error: an unsigned value with a negative constant +} + +macro obfuscate(x, $foo) +{ + return $foo == x; +} + +fn bool test7(uint x) +{ + return obfuscate(x, -1); +} \ No newline at end of file diff --git a/test/test_suite2/failable_catch.c3t b/test/test_suite2/failable_catch.c3t new file mode 100644 index 000000000..c9710fb23 --- /dev/null +++ b/test/test_suite2/failable_catch.c3t @@ -0,0 +1,176 @@ +// #target: macos-x64 + +fault MyErr +{ + TEST +} + +macro foo(int x) +{ + if (x) return x; + return MyErr.TEST!; +} + +extern fn void printf(char*, ...); + +fn int main() +{ + int! a = foo(1); + + int! b = foo((a + 3) ?? 2); + int! c = foo(0); + printf("a = %d\n", a); + printf("b = %d\n", b); + printf("c = %d\n", c); + if (catch(c)) printf("c had error\n"); + c = 3; + printf("c = %d\n", c); + return 0; +} + +/* #expect: failable_catch.ll + +define i32 @main() #0 { +entry: + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %x = alloca i32, align 4 + %blockret = alloca i32, align 4 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + %x1 = alloca i32, align 4 + %blockret2 = alloca i32, align 4 + %c = alloca i32, align 4 + %c.f = alloca i64, align 8 + %x8 = alloca i32, align 4 + %blockret9 = alloca i32, align 4 + store i32 1, ptr %x, align 4 + %0 = load i32, ptr %x, align 4 + %intbool = icmp ne i32 %0, 0 + br i1 %intbool, label %if.then, label %if.exit + +if.then: ; preds = %entry + %1 = load i32, ptr %x, align 4 + store i32 %1, ptr %blockret, align 4 + br label %expr_block.exit + +if.exit: ; preds = %entry + store i64 ptrtoint (ptr @failable_catch.MyErr.TEST to i64), ptr %a.f, align 8 + br label %after_assign + +expr_block.exit: ; preds = %if.then + %2 = load i32, ptr %blockret, align 4 + store i32 %2, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + br label %after_assign + +after_assign: ; preds = %expr_block.exit, %if.exit + %3 = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %3, 0 + br i1 %not_err, label %after_check, label %else_block + +after_check: ; preds = %after_assign + %4 = load i32, ptr %a, align 4 + %add = add i32 %4, 3 + br label %phi_block + +else_block: ; preds = %after_assign + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val = phi i32 [ %add, %after_check ], [ 2, %else_block ] + store i32 %val, ptr %x1, align 4 + %5 = load i32, ptr %x1, align 4 + %intbool3 = icmp ne i32 %5, 0 + br i1 %intbool3, label %if.then4, label %if.exit5 + +if.then4: ; preds = %phi_block + %6 = load i32, ptr %x1, align 4 + store i32 %6, ptr %blockret2, align 4 + br label %expr_block.exit6 + +if.exit5: ; preds = %phi_block + store i64 ptrtoint (ptr @failable_catch.MyErr.TEST to i64), ptr %b.f, align 8 + br label %after_assign7 + +expr_block.exit6: ; preds = %if.then4 + %7 = load i32, ptr %blockret2, align 4 + store i32 %7, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign7 + +after_assign7: ; preds = %expr_block.exit6, %if.exit5 + store i32 0, ptr %x8, align 4 + %8 = load i32, ptr %x8, align 4 + %intbool10 = icmp ne i32 %8, 0 + br i1 %intbool10, label %if.then11, label %if.exit12 + +if.then11: ; preds = %after_assign7 + %9 = load i32, ptr %x8, align 4 + store i32 %9, ptr %blockret9, align 4 + br label %expr_block.exit13 + +if.exit12: ; preds = %after_assign7 + store i64 ptrtoint (ptr @failable_catch.MyErr.TEST to i64), ptr %c.f, align 8 + br label %after_assign14 + +expr_block.exit13: ; preds = %if.then11 + %10 = load i32, ptr %blockret9, align 4 + store i32 %10, ptr %c, align 4 + store i64 0, ptr %c.f, align 8 + br label %after_assign14 + +after_assign14: ; preds = %expr_block.exit13, %if.exit12 + %11 = load i64, ptr %a.f, align 8 + %not_err15 = icmp eq i64 %11, 0 + br i1 %not_err15, label %after_check16, label %voiderr + +after_check16: ; preds = %after_assign14 + %12 = load i32, ptr %a, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %12) + br label %voiderr + +voiderr: ; preds = %after_check16, %after_assign14 + %13 = load i64, ptr %b.f, align 8 + %not_err17 = icmp eq i64 %13, 0 + br i1 %not_err17, label %after_check18, label %voiderr19 + +after_check18: ; preds = %voiderr + %14 = load i32, ptr %b, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %14) + br label %voiderr19 + +voiderr19: ; preds = %after_check18, %voiderr + %15 = load i64, ptr %c.f, align 8 + %not_err20 = icmp eq i64 %15, 0 + br i1 %not_err20, label %after_check21, label %voiderr22 + +after_check21: ; preds = %voiderr19 + %16 = load i32, ptr %c, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %16) + br label %voiderr22 + +voiderr22: ; preds = %after_check21, %voiderr19 + %17 = load i64, ptr %c.f, align 8 + %neq = icmp ne i64 %17, 0 + br i1 %neq, label %if.then23, label %if.exit24 + +if.then23: ; preds = %voiderr22 + call void (ptr, ...) @printf(ptr @.str.3) + br label %if.exit24 + +if.exit24: ; preds = %if.then23, %voiderr22 + store i32 3, ptr %c, align 4 + store i64 0, ptr %c.f, align 8 + %18 = load i64, ptr %c.f, align 8 + %not_err25 = icmp eq i64 %18, 0 + br i1 %not_err25, label %after_check26, label %voiderr27 + +after_check26: ; preds = %if.exit24 + %19 = load i32, ptr %c, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %19) + br label %voiderr27 + +voiderr27: ; preds = %after_check26, %if.exit24 + ret i32 0 +} diff --git a/test/test_suite2/floats/convert_float.c3t b/test/test_suite2/floats/convert_float.c3t new file mode 100644 index 000000000..cb06a173e --- /dev/null +++ b/test/test_suite2/floats/convert_float.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module foo; + +fn void test() +{ + float x = 12; + x *= -1; + double y = x; +} + +/* #expect: foo.ll +define void @foo.test() #0 { +entry: + %x = alloca float, align 4 + %y = alloca double, align 8 + store float 1.200000e+01, ptr %x, align 4 + %0 = load float, ptr %x, align 4 + %fmul = fmul float %0, -1.000000e+00 + store float %fmul, ptr %x, align 4 + %1 = load float, ptr %x, align 4 + %fpfpext = fpext float %1 to double + store double %fpfpext, ptr %y, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/floats/explicit_float_truncation_needed.c3 b/test/test_suite2/floats/explicit_float_truncation_needed.c3 new file mode 100644 index 000000000..72774ec8c --- /dev/null +++ b/test/test_suite2/floats/explicit_float_truncation_needed.c3 @@ -0,0 +1,4 @@ +fn void test() +{ + float x = 0x7FFFFFFFFFFF.0p+400; // #error: The value '3.63419e+134' is out of range for 'float' +} \ No newline at end of file diff --git a/test/test_suite2/floats/float_exceeding_size.c3 b/test/test_suite2/floats/float_exceeding_size.c3 new file mode 100644 index 000000000..88867f28f --- /dev/null +++ b/test/test_suite2/floats/float_exceeding_size.c3 @@ -0,0 +1,5 @@ +fn void test() +{ + float x = 0x7FFFFFFFFFFF.0p+40000; // #error: The float value is out of range. + +} \ No newline at end of file diff --git a/test/test_suite2/floats/inf_nan.c3t b/test/test_suite2/floats/inf_nan.c3t new file mode 100644 index 000000000..a0c712bc7 --- /dev/null +++ b/test/test_suite2/floats/inf_nan.c3t @@ -0,0 +1,26 @@ +module fe; + +fn void main() +{ + float z = float.inf + 100; + double z2 = double.inf; + float g = float.nan; + double g2 = double.nan; + double x = (double)(z); +} + +/* #expect: fe.ll + + %z = alloca float, align 4 + %z2 = alloca double, align 8 + %g = alloca float, align 4 + %g2 = alloca double, align 8 + %x = alloca double, align 8 + store float 0x7FF0000000000000, ptr %z, align 4 + store double 0x7FF0000000000000, ptr %z2, align 8 + store float 0x7FF8000000000000, ptr %g, align 4 + store double 0x7FF8000000000000, ptr %g2, align 8 + %0 = load float, ptr %z, align 4 + %fpfpext = fpext float %0 to double + store double %fpfpext, ptr %x, align 8 + ret void \ No newline at end of file diff --git a/test/test_suite2/from_docs/examples_defer.c3t b/test/test_suite2/from_docs/examples_defer.c3t new file mode 100644 index 000000000..42ec2e56b --- /dev/null +++ b/test/test_suite2/from_docs/examples_defer.c3t @@ -0,0 +1,61 @@ +// #target: macos-x64 +module defer1; +import std::io; + +fn void test(int x) +{ + defer io::println(); + defer io::print("A"); + if (x == 1) return; + { + defer io::print("B"); + if (x == 0) return; + } + io::print("!"); +} + +fn void main() +{ + test(1); // Prints "A" + test(0); // Prints "BA" + test(10); // Prints "B!A" +} + +/* #expect: defer1.ll + +define void @defer1.test(i32 %0) #0 { +entry: + %eq = icmp eq i32 %0, 1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + %1 = call i32 @"std::io.print"(ptr @.str) + %2 = call i32 @"std::io.println"(ptr @.str.1) #1 + ret void + +if.exit: ; preds = %entry + %eq1 = icmp eq i32 %0, 0 + br i1 %eq1, label %if.then2, label %if.exit3 + +if.then2: ; preds = %if.exit + %3 = call i32 @"std::io.print"(ptr @.str.2) + %4 = call i32 @"std::io.print"(ptr @.str.3) + %5 = call i32 @"std::io.println"(ptr @.str.4) #1 + ret void + +if.exit3: ; preds = %if.exit + %6 = call i32 @"std::io.print"(ptr @.str.5) + %7 = call i32 @"std::io.print"(ptr @.str.6) + %8 = call i32 @"std::io.print"(ptr @.str.7) + %9 = call i32 @"std::io.println"(ptr @.str.8) #1 + ret void +} + +; Function Attrs: nounwind +define void @defer1.main() #0 { +entry: + call void @defer1.test(i32 1) + call void @defer1.test(i32 0) + call void @defer1.test(i32 10) + ret void +} diff --git a/test/test_suite2/from_docs/examples_forswitch.c3t b/test/test_suite2/from_docs/examples_forswitch.c3t new file mode 100644 index 000000000..21fad4b84 --- /dev/null +++ b/test/test_suite2/from_docs/examples_forswitch.c3t @@ -0,0 +1,237 @@ +// #target: macos-x64 +module examples; +import libc; +import std::io; + +fn void example_for() +{ + // the for-loop is the same as C99. + for (int i = 0; i < 10; i++) + { + libc::printf("%d\n", i); + } + + // also equal + for (;;) + { + // .. + } +} + +enum Height : uint +{ + LOW, + MEDIUM, + HIGH, +} + +fn void demo_enum(Height h) +{ + switch (h) + { + case LOW: + case MEDIUM: + io::println("Not high"); + // Implicit break. + case HIGH: + io::println("High"); + } + + // This also works + switch (h) + { + case LOW: + case MEDIUM: + io::println("Not high"); + // Implicit break. + case Height.HIGH: + io::println("High"); + } + + // Completely empty cases are not allowed. + switch (h) + { + case LOW: + break; // Explicit break required, since switches can't be empty. + case MEDIUM: + io::println("Medium"); + case HIGH: + break; + } + + // special checking of switching on enum types + switch (h) + { + case LOW: + case MEDIUM: + case HIGH: + break; + default: // warning: default label in switch which covers all enumeration value + break; + } + + // Using "nextcase" will fallthrough to the next case statement, + // and each case statement starts its own scope. + switch (h) + { + case LOW: + int a = 1; + io::println("A"); + nextcase; + case MEDIUM: + int a = 2; + io::println("B"); + nextcase; + case HIGH: + // a is not defined here + io::println("C"); + } +} +/* #expect: examples.ll + + +define void @examples.example_for() #0 { +entry: + %i = alloca i32, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %0 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %0, 10 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i32, ptr %i, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str, i32 %1) + %3 = load i32, ptr %i, align 4 + %add = add i32 %3, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + call void @"std::core::builtin.panic"(ptr @.zstr, ptr @.zstr.1, ptr @.zstr.2, i32 14) + unreachable + +unreachable_block: ; No predecessors! + ret void +} + +; Function Attrs: nounwind +define void @examples.demo_enum(i32 %0) #0 { +entry: + %switch = alloca i32, align 4 + %switch2 = alloca i32, align 4 + %switch7 = alloca i32, align 4 + %switch13 = alloca i32, align 4 + %switch17 = alloca i32, align 4 + %a = alloca i32, align 4 + %a21 = alloca i32, align 4 + store i32 %0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %1 = load i32, ptr %switch, align 4 + switch i32 %1, label %switch.exit [ + i32 0, label %switch.case + i32 1, label %switch.case + i32 2, label %switch.case1 + ] + +switch.case: ; preds = %switch.entry, %switch.entry + %2 = call i32 @"std::io.println"(ptr @.str.3) #1 + br label %switch.exit + +switch.case1: ; preds = %switch.entry + %3 = call i32 @"std::io.println"(ptr @.str.4) #1 + br label %switch.exit + +switch.exit: ; preds = %switch.case1, %switch.case, %switch.entry + store i32 %0, ptr %switch2, align 4 + br label %switch.entry3 + +switch.entry3: ; preds = %switch.exit + %4 = load i32, ptr %switch2, align 4 + switch i32 %4, label %switch.exit6 [ + i32 0, label %switch.case4 + i32 1, label %switch.case4 + i32 2, label %switch.case5 + ] + +switch.case4: ; preds = %switch.entry3, %switch.entry3 + %5 = call i32 @"std::io.println"(ptr @.str.5) #1 + br label %switch.exit6 + +switch.case5: ; preds = %switch.entry3 + %6 = call i32 @"std::io.println"(ptr @.str.6) #1 + br label %switch.exit6 + +switch.exit6: ; preds = %switch.case5, %switch.case4, %switch.entry3 + store i32 %0, ptr %switch7, align 4 + br label %switch.entry8 + +switch.entry8: ; preds = %switch.exit6 + %7 = load i32, ptr %switch7, align 4 + switch i32 %7, label %switch.exit12 [ + i32 0, label %switch.case9 + i32 1, label %switch.case10 + i32 2, label %switch.case11 + ] + +switch.case9: ; preds = %switch.entry8 + br label %switch.exit12 + +switch.case10: ; preds = %switch.entry8 + %8 = call i32 @"std::io.println"(ptr @.str.7) #1 + br label %switch.exit12 + +switch.case11: ; preds = %switch.entry8 + br label %switch.exit12 + +switch.exit12: ; preds = %switch.case11, %switch.case10, %switch.case9, %switch.entry8 + store i32 %0, ptr %switch13, align 4 + br label %switch.entry14 + +switch.entry14: ; preds = %switch.exit12 + %9 = load i32, ptr %switch13, align 4 + switch i32 %9, label %switch.default [ + i32 0, label %switch.case15 + i32 1, label %switch.case15 + i32 2, label %switch.case15 + ] + +switch.case15: ; preds = %switch.entry14, %switch.entry14, %switch.entry14 + br label %switch.exit16 + +switch.default: ; preds = %switch.entry14 + br label %switch.exit16 + +switch.exit16: ; preds = %switch.default, %switch.case15 + store i32 %0, ptr %switch17, align 4 + br label %switch.entry18 + +switch.entry18: ; preds = %switch.exit16 + %10 = load i32, ptr %switch17, align 4 + switch i32 %10, label %switch.exit23 [ + i32 0, label %switch.case19 + i32 1, label %switch.case20 + i32 2, label %switch.case22 + ] + +switch.case19: ; preds = %switch.entry18 + store i32 1, ptr %a, align 4 + %11 = call i32 @"std::io.println"(ptr @.str.8) #1 + br label %switch.case20 + +switch.case20: ; preds = %switch.entry18, %switch.case19 + store i32 2, ptr %a21, align 4 + %12 = call i32 @"std::io.println"(ptr @.str.9) #1 + br label %switch.case22 + +switch.case22: ; preds = %switch.entry18, %switch.case20 + %13 = call i32 @"std::io.println"(ptr @.str.10) #1 + br label %switch.exit23 + +switch.exit23: ; preds = %switch.case22, %switch.entry18 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/from_docs/examples_functionpointer.c3t b/test/test_suite2/from_docs/examples_functionpointer.c3t new file mode 100644 index 000000000..8b36b2134 --- /dev/null +++ b/test/test_suite2/from_docs/examples_functionpointer.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 + +module demo; +define Callback = fn int(char* text, int value); + +fn int my_callback(char* text, int value) +{ + return 0; +} + +Callback cb = &my_callback; + +fn void main() +{ + int result = cb("demo", 123); + // .. +} + +/* #expect: demo.ll + + +define i32 @demo.my_callback(ptr %0, i32 %1) #0 { +entry: + ret i32 0 +} + +define void @demo.main() #0 { +entry: + %result = alloca i32, align 4 + %0 = load ptr, ptr @demo.cb, align 8 + %1 = call i32 %0(ptr @.str, i32 123) + store i32 %1, ptr %result, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/from_docs/examples_if_catch.c3t b/test/test_suite2/from_docs/examples_if_catch.c3t new file mode 100644 index 000000000..893fd1ac6 --- /dev/null +++ b/test/test_suite2/from_docs/examples_if_catch.c3t @@ -0,0 +1,161 @@ +// #target: macos-x64 +module demo; +import libc; +import std::io; + +fault MathError +{ + DIVISION_BY_ZERO +} + +fn int foo() { return 123; } +fn int bar() { return 0; } + +fn double! divide(int a, int b) +{ + if (b == 0) return MathError.DIVISION_BY_ZERO!; + return (double)(a) / (double)(b); + +} + +// Rethrowing an error uses "?" suffix +fn void! testMayError() +{ + divide(foo(), bar())?; +} + +fn void main() +{ + // ratio has a failable type. + double! ratio = divide(foo(), bar()); + + // Handle the error + if (catch err = ratio) + { + case MathError.DIVISION_BY_ZERO: + libc::printf("Division by zero\n"); + return; + default: + libc::printf("Unexpected error!"); + return; + } + // Flow typing makes "ratio" + // have the type double here. + libc::printf("Ratio was %f\n", ratio); +} + +/* #expect: demo.ll + + +define i64 @demo.divide(ptr %0, i32 %1, i32 %2) #0 { +entry: + %reterr = alloca i64, align 8 + %eq = icmp eq i32 %2, 0 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @demo.MathError.DIVISION_BY_ZERO to i64) + +if.exit: ; preds = %entry + %sifp = sitofp i32 %1 to double + %sifp1 = sitofp i32 %2 to double + %fdiv = fdiv double %sifp, %sifp1 + store double %fdiv, ptr %0, align 8 + ret i64 0 +} + +define i64 @demo.testMayError() #0 { +entry: + %error_var = alloca i64, align 8 + %retparam = alloca double, align 8 + %reterr = alloca i64, align 8 + %0 = call i32 @demo.foo() + %1 = call i32 @demo.bar() + %2 = call i64 @demo.divide(ptr %retparam, i32 %0, i32 %1) + %not_err = icmp eq i64 %2, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block + +after.errcheck: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %error + %3 = load i64, ptr %error_var, align 8 + ret i64 %3 + +noerr_block: ; preds = %after.errcheck + ret i64 0 +} + +define void @demo.main() #0 { +entry: + %ratio = alloca double, align 8 + %ratio.f = alloca i64, align 8 + %retparam = alloca double, align 8 + %err = alloca i64, align 8 + %switch = alloca i64, align 8 + %0 = call i32 @demo.foo() + %1 = call i32 @demo.bar() + %2 = call i64 @demo.divide(ptr %retparam, i32 %0, i32 %1) + %not_err = icmp eq i64 %2, 0 + br i1 %not_err, label %after.errcheck, label %error + +error: ; preds = %entry + store i64 %2, ptr %ratio.f, align 8 + br label %after_assign + +after.errcheck: ; preds = %entry + %3 = load double, ptr %retparam, align 8 + store double %3, ptr %ratio, align 8 + store i64 0, ptr %ratio.f, align 8 + br label %after_assign + +after_assign: ; preds = %after.errcheck, %error + br label %testblock + +testblock: ; preds = %after_assign + %4 = load i64, ptr %ratio.f, align 8 + %not_err1 = icmp eq i64 %4, 0 + br i1 %not_err1, label %after_check, label %error2 + +error2: ; preds = %testblock + store i64 %4, ptr %err, align 8 + br label %end_block + +after_check: ; preds = %testblock + store i64 0, ptr %err, align 8 + br label %end_block + +end_block: ; preds = %after_check, %error2 + %5 = load i64, ptr %err, align 8 + %neq = icmp ne i64 %5, 0 + br i1 %neq, label %if.then, label %if.exit + +if.then: ; preds = %end_block + store i64 %5, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %if.then + %6 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @demo.MathError.DIVISION_BY_ZERO to i64), %6 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + %7 = call i32 (ptr, ...) @printf(ptr @.str) + ret void + +next_if: ; preds = %switch.entry + br label %switch.default + +switch.default: ; preds = %next_if + %8 = call i32 (ptr, ...) @printf(ptr @.str.1) + ret void + +if.exit: ; preds = %end_block + %9 = load double, ptr %ratio, align 8 + %10 = call i32 (ptr, ...) @printf(ptr @.str.2, double %9) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/from_docs/examples_macro_function.c3t b/test/test_suite2/from_docs/examples_macro_function.c3t new file mode 100644 index 000000000..860ed506b --- /dev/null +++ b/test/test_suite2/from_docs/examples_macro_function.c3t @@ -0,0 +1,50 @@ +// #target: macos-x64 +module example; +import std::io; + +macro foo(a, b) +{ + return a(b); +} + +fn int square(int x) +{ + return x * x; +} + +fn int test() +{ + int a = 2; + int b = 3; + return foo(&square, 2) + a + b; // 9 + // return foo(square, 2) + a + b; + // Error the symbol "square" cannot be used as an argument. +} + +/* #expect: example.ll + +define i32 @example.square(i32 %0) #0 { +entry: + %mul = mul i32 %0, %0 + ret i32 %mul +} + +define i32 @example.test() #0 { +entry: + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %a1 = alloca ptr, align 8 + %b2 = alloca i32, align 4 + store i32 2, ptr %a, align 4 + store i32 3, ptr %b, align 4 + store ptr @example.square, ptr %a1, align 8 + store i32 2, ptr %b2, align 4 + %0 = load ptr, ptr %a1, align 8 + %1 = load i32, ptr %b2, align 4 + %2 = call i32 %0(i32 %1) + %3 = load i32, ptr %a, align 4 + %add = add i32 %2, %3 + %4 = load i32, ptr %b, align 4 + %add3 = add i32 %add, %4 + ret i32 %add3 +} \ No newline at end of file diff --git a/test/test_suite2/from_docs/examples_struct.c3 b/test/test_suite2/from_docs/examples_struct.c3 new file mode 100644 index 000000000..dccc7d404 --- /dev/null +++ b/test/test_suite2/from_docs/examples_struct.c3 @@ -0,0 +1,46 @@ +define Callback = fn int(char c); +struct Person { int i; } +struct Company { int j; } +enum Status : int +{ + IDLE, + BUSY, + DONE, +} + +struct MyData +{ + char* name; + Callback open; + Callback close; + //Status status; + + // named sub-structs (x.other.value) + struct other + { + int value; + int status; // ok, no name clash with other status + } + + // anonymous sub-structs (x.value) + struct + { + int value; + int status; // error, name clash with other status in MyData + } + + // anonymous union (x.person) + union + { + Person* person; + Company* company; + } + + // named sub-unions (x.either.this) + union either + { + int this; + bool or; + char* that; + } +} \ No newline at end of file diff --git a/test/test_suite2/functions/assorted_tests.c3t b/test/test_suite2/functions/assorted_tests.c3t new file mode 100644 index 000000000..2efdb1bb6 --- /dev/null +++ b/test/test_suite2/functions/assorted_tests.c3t @@ -0,0 +1,110 @@ +module test; + +fn int foo1() +{ + char *pp = void; + uint w_cnt = void; + + w_cnt += *pp; + + return (int)(w_cnt); +} + +extern fn void test2(int, double, float); + +fn void foo2(int x) +{ + test2(x, x ? 1.0 : 12.5, 1.0); +} + +fn int trys(ichar* s, int x) +{ + int asa = void; + double val = void; + int lls = void; + if (x) + { + asa = lls + asa; + } + else + { + } + return asa + (int)(val); +} + +struct InternalFPF +{ + char type; +} + +fn void setInternalFPFZero(InternalFPF* dest) @noinline +{ + dest.type = 0; +} + +fn void denormalize(InternalFPF* ptr) +{ + setInternalFPFZero(ptr); +} + + +/* #expect: test.ll + + +define i32 @test.foo1() #0 { +entry: + %pp = alloca ptr, align 8 + %w_cnt = alloca i32, align 4 + %0 = load i32, ptr %w_cnt, align 4 + %1 = load ptr, ptr %pp, align 8 + %2 = load i8, ptr %1, align 8 + %uiuiext = zext i8 %2 to i32 + %add = add i32 %0, %uiuiext + store i32 %add, ptr %w_cnt, align 4 + %3 = load i32, ptr %w_cnt, align 4 + ret i32 %3 +} + +define void @test.foo2(i32 %0) #0 { +entry: + %intbool = icmp ne i32 %0, 0 + %ternary = select i1 %intbool, double 1.000000e+00, double 1.250000e+01 + call void @test2(i32 %0, double %ternary, float 1.000000e+00) + ret void +} + +define i32 @test.trys(ptr %0, i32 %1) #0 { +entry: + %asa = alloca i32, align 4 + %val = alloca double, align 8 + %lls = alloca i32, align 4 + %intbool = icmp ne i32 %1, 0 + br i1 %intbool, label %if.then, label %if.exit + +if.then: ; preds = %entry + %2 = load i32, ptr %lls, align 4 + %3 = load i32, ptr %asa, align 4 + %add = add i32 %2, %3 + store i32 %add, ptr %asa, align 4 + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %4 = load i32, ptr %asa, align 4 + %5 = load double, ptr %val, align 8 + %fpsi = fptosi double %5 to i32 + %add1 = add i32 %4, %fpsi + ret i32 %add1 +} + +define void @test.setInternalFPFZero(ptr %0) #1 { +entry: + %1 = getelementptr inbounds %InternalFPF, ptr %0, i32 0, i32 0 + store i8 0, ptr %1, align 8 + ret void +} + +define void @test.denormalize(ptr %0) #0 { +entry: + call void @test.setInternalFPFZero(ptr %0) + ret void +} diff --git a/test/test_suite2/functions/body_argument_fail.c3 b/test/test_suite2/functions/body_argument_fail.c3 new file mode 100644 index 000000000..7af99bcf5 --- /dev/null +++ b/test/test_suite2/functions/body_argument_fail.c3 @@ -0,0 +1,5 @@ +fn void foo1(int... x;) {} // #error: Expected ')' +fn void foo2(... x;) {} // #error: Expected ')' +fn void foo3(... x;) {} // #error: Expected ')' +fn void foo4(;) {} // #error: Expected ')' +fn void foo5(int x;) {} // #error: Expected ')' \ No newline at end of file diff --git a/test/test_suite2/functions/default_param_fail.c3 b/test/test_suite2/functions/default_param_fail.c3 new file mode 100644 index 000000000..95d284f8c --- /dev/null +++ b/test/test_suite2/functions/default_param_fail.c3 @@ -0,0 +1,11 @@ + +int z; + +fault MyError +{ + FOO, +} + +fn void test(int a = z) {} // #error: Only constant expressions may be used as default values + +fn void test2(int b = MyError.FOO!) {} // #error: Default arguments may not be failable \ No newline at end of file diff --git a/test/test_suite2/functions/double_return.c3t b/test/test_suite2/functions/double_return.c3t new file mode 100644 index 000000000..752700bce --- /dev/null +++ b/test/test_suite2/functions/double_return.c3t @@ -0,0 +1,13 @@ +module double_return; + +fn int test(bool pos, bool color) +{ + return 0; + return (int)(pos && color); +} + +// #expect: double_return.ll + +entry: + ret i32 0 +} diff --git a/test/test_suite2/functions/macro_arguments.c3 b/test/test_suite2/functions/macro_arguments.c3 new file mode 100644 index 000000000..88ca22ee6 --- /dev/null +++ b/test/test_suite2/functions/macro_arguments.c3 @@ -0,0 +1,10 @@ + +fn void foo1(int #foo) { } // #error: Only regular parameters are allowed for functions. + +fn void foo2(int $foo) { } // #error: Only regular parameters are allowed for functions. + +fn void foo3(bar) { } // #error: Only typed parameters are allowed for functions + +fn void foo4($Type) { } // #error: Only regular parameters are allowed for functions. + +fn void foo8(int &foo) {} // #error: Only regular parameters are allowed for functions. \ No newline at end of file diff --git a/test/test_suite2/functions/missing_first_paren.c3 b/test/test_suite2/functions/missing_first_paren.c3 new file mode 100644 index 000000000..384625bd2 --- /dev/null +++ b/test/test_suite2/functions/missing_first_paren.c3 @@ -0,0 +1,3 @@ +fn void foo) // #error: Expected '(' +{ +} diff --git a/test/test_suite2/functions/missing_return.c3 b/test/test_suite2/functions/missing_return.c3 new file mode 100644 index 000000000..d1028c19b --- /dev/null +++ b/test/test_suite2/functions/missing_return.c3 @@ -0,0 +1,3 @@ +fn int test1() // #error: Missing return statement at the end of +{ +} \ No newline at end of file diff --git a/test/test_suite2/functions/naked_function.c3t b/test/test_suite2/functions/naked_function.c3t new file mode 100644 index 000000000..d5bde17d6 --- /dev/null +++ b/test/test_suite2/functions/naked_function.c3t @@ -0,0 +1,15 @@ +// #target: macos-x64 + +fn void test(int i) @naked +{ + +} + +// #expect: naked_function.ll + +define void @naked_function.test(i32 %0) #0 { +entry: + ret void +} + +attributes #0 = { naked nounwind } \ No newline at end of file diff --git a/test/test_suite2/functions/naked_function_fail.c3 b/test/test_suite2/functions/naked_function_fail.c3 new file mode 100644 index 000000000..df2b693f7 --- /dev/null +++ b/test/test_suite2/functions/naked_function_fail.c3 @@ -0,0 +1,4 @@ +fn void test() @naked +{ + int i; // #error: Only asm statements are allowed inside of a naked function +} \ No newline at end of file diff --git a/test/test_suite2/functions/returning_void.c3t b/test/test_suite2/functions/returning_void.c3t new file mode 100644 index 000000000..e93e09790 --- /dev/null +++ b/test/test_suite2/functions/returning_void.c3t @@ -0,0 +1,20 @@ +fn void test1() +{ + int x; + if (x == 0) return; + return test1(); +} +// #expect: returning_void.ll + + %x = alloca i32, align 4 + store i32 0, ptr %x, align 4 + %0 = load i32, ptr %x, align 4 + %eq = icmp eq i32 %0, 0 + br i1 %eq, label %if.then, label %if.exit + +if.then: + ret void + +if.exit: + call void @returning_void.test1() + ret void diff --git a/test/test_suite2/functions/splat.c3t b/test/test_suite2/functions/splat.c3t new file mode 100644 index 000000000..875f1e99b --- /dev/null +++ b/test/test_suite2/functions/splat.c3t @@ -0,0 +1,68 @@ +// #target: macos-x64 +module splat; + +extern fn int sum_us(int... x); + +fn void test() +{ + sum_us(1, 2, 3); + int[3] x = { 1, 2, 3 }; + int[] z = &x; + sum_us(...x); + sum_us(...z); + sum_us(); +} + +/* #expect: splat.ll + + + %vararg = alloca %"int[]", align 8 + %varargslots = alloca [3 x i32], align 4 + %x = alloca [3 x i32], align 4 + %z = alloca %"int[]", align 8 + %vararg1 = alloca %"int[]", align 8 + %vararg4 = alloca %"int[]", align 8 + %vararg7 = alloca %"int[]", align 8 + %0 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 0 + store i32 1, ptr %0, align 4 + %1 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 1 + store i32 2, ptr %1, align 4 + %2 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 2 + store i32 3, ptr %2, align 4 + %3 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 1 + store i64 3, ptr %3, align 8 + %4 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo = load ptr, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi = load i64, ptr %6, align 8 + %7 = call i32 @sum_us(ptr %lo, i64 %hi) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %8 = insertvalue %"int[]" undef, ptr %x, 0 + %9 = insertvalue %"int[]" %8, i64 3, 1 + store %"int[]" %9, ptr %z, align 8 + %10 = getelementptr inbounds %"int[]", ptr %vararg1, i32 0, i32 1 + %11 = getelementptr inbounds %"int[]", ptr %vararg1, i32 0, i32 0 + store i64 3, ptr %10, align 8 + store ptr %x, ptr %11, align 8 + %12 = getelementptr inbounds { ptr, i64 }, ptr %vararg1, i32 0, i32 0 + %lo2 = load ptr, ptr %12, align 8 + %13 = getelementptr inbounds { ptr, i64 }, ptr %vararg1, i32 0, i32 1 + %hi3 = load i64, ptr %13, align 8 + %14 = call i32 @sum_us(ptr %lo2, i64 %hi3) + %15 = getelementptr inbounds %"int[]", ptr %vararg4, i32 0, i32 1 + %16 = getelementptr inbounds %"int[]", ptr %vararg4, i32 0, i32 0 + %17 = getelementptr inbounds { ptr, i64 }, ptr %z, i32 0, i32 0 + %lo5 = load ptr, ptr %17, align 8 + %18 = getelementptr inbounds { ptr, i64 }, ptr %z, i32 0, i32 1 + %hi6 = load i64, ptr %18, align 8 + %19 = call i32 @sum_us(ptr %lo5, i64 %hi6) + %20 = getelementptr inbounds %"int[]", ptr %vararg7, i32 0, i32 1 + store i64 0, ptr %20, align 8 + %21 = getelementptr inbounds { ptr, i64 }, ptr %vararg7, i32 0, i32 0 + %lo8 = load ptr, ptr %21, align 8 + %22 = getelementptr inbounds { ptr, i64 }, ptr %vararg7, i32 0, i32 1 + %hi9 = load i64, ptr %22, align 8 + %23 = call i32 @sum_us(ptr %lo8, i64 %hi9) + ret void diff --git a/test/test_suite2/functions/splat_aarch64.c3t b/test/test_suite2/functions/splat_aarch64.c3t new file mode 100644 index 000000000..a61883997 --- /dev/null +++ b/test/test_suite2/functions/splat_aarch64.c3t @@ -0,0 +1,71 @@ +// #target: linux-aarch64 +module splat; + +extern fn int sum_us(int... x); + +fn void test() +{ + sum_us(1, 2, 3); + int[3] x = { 1, 2, 3 }; + int[] z = &x; + sum_us(...x); + sum_us(...z); + sum_us(); +} + +/* #expect: splat.ll + + +%"int[]" = type { ptr, i64 } + +declare i32 @sum_us([2 x i64]) #0 + +define void @splat.test() #0 { +entry: + %vararg = alloca %"int[]", align 8 + %varargslots = alloca [3 x i32], align 4 + %tempcoerce = alloca [2 x i64], align 8 + %x = alloca [3 x i32], align 4 + %z = alloca %"int[]", align 8 + %vararg1 = alloca %"int[]", align 8 + %tempcoerce2 = alloca [2 x i64], align 8 + %vararg3 = alloca %"int[]", align 8 + %tempcoerce4 = alloca [2 x i64], align 8 + %vararg5 = alloca %"int[]", align 8 + %tempcoerce6 = alloca [2 x i64], align 8 + %0 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 0 + store i32 1, ptr %0, align 4 + %1 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 1 + store i32 2, ptr %1, align 4 + %2 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 2 + store i32 3, ptr %2, align 4 + %3 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 1 + store i64 3, ptr %3, align 8 + %4 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %4, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %vararg, i32 16, i1 false) + %5 = load [2 x i64], ptr %tempcoerce, align 8 + %6 = call i32 @sum_us([2 x i64] %5) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %7 = insertvalue %"int[]" undef, ptr %x, 0 + %8 = insertvalue %"int[]" %7, i64 3, 1 + store %"int[]" %8, ptr %z, align 8 + %9 = getelementptr inbounds %"int[]", ptr %vararg1, i32 0, i32 1 + %10 = getelementptr inbounds %"int[]", ptr %vararg1, i32 0, i32 0 + store i64 3, ptr %9, align 8 + store ptr %x, ptr %10, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce2, ptr align 8 %vararg1, i32 16, i1 false) + %11 = load [2 x i64], ptr %tempcoerce2, align 8 + %12 = call i32 @sum_us([2 x i64] %11) + %13 = getelementptr inbounds %"int[]", ptr %vararg3, i32 0, i32 1 + %14 = getelementptr inbounds %"int[]", ptr %vararg3, i32 0, i32 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce4, ptr align 8 %z, i32 16, i1 false) + %15 = load [2 x i64], ptr %tempcoerce4, align 8 + %16 = call i32 @sum_us([2 x i64] %15) + %17 = getelementptr inbounds %"int[]", ptr %vararg5, i32 0, i32 1 + store i64 0, ptr %17, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce6, ptr align 8 %vararg5, i32 16, i1 false) + %18 = load [2 x i64], ptr %tempcoerce6, align 8 + %19 = call i32 @sum_us([2 x i64] %18) + ret void +} diff --git a/test/test_suite2/functions/splat_mingw.c3t b/test/test_suite2/functions/splat_mingw.c3t new file mode 100644 index 000000000..3323662fc --- /dev/null +++ b/test/test_suite2/functions/splat_mingw.c3t @@ -0,0 +1,61 @@ +// #target: mingw-x64 +module splat; + +extern fn int sum_us(int... x); + +fn void test() +{ + sum_us(1, 2, 3); + int[3] x = { 1, 2, 3 }; + int[] z = &x; + sum_us(...x); + sum_us(...z); + sum_us(); +} + +/* #expect: splat.ll + +define void @splat.test() #0 { +entry: + %vararg = alloca %"int[]", align 8 + %varargslots = alloca [3 x i32], align 4 + %indirectarg = alloca %"int[]", align 8 + %x = alloca [3 x i32], align 4 + %z = alloca %"int[]", align 8 + %vararg1 = alloca %"int[]", align 8 + %indirectarg2 = alloca %"int[]", align 8 + %vararg3 = alloca %"int[]", align 8 + %indirectarg4 = alloca %"int[]", align 8 + %vararg5 = alloca %"int[]", align 8 + %indirectarg6 = alloca %"int[]", align 8 + %0 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 0 + store i32 1, ptr %0, align 4 + %1 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 1 + store i32 2, ptr %1, align 4 + %2 = getelementptr inbounds [3 x i32], ptr %varargslots, i64 0, i64 2 + store i32 3, ptr %2, align 4 + %3 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 1 + store i64 3, ptr %3, align 8 + %4 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %4, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %vararg, i32 16, i1 false) + %5 = call i32 @sum_us(ptr %indirectarg) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %6 = insertvalue %"int[]" undef, ptr %x, 0 + %7 = insertvalue %"int[]" %6, i64 3, 1 + store %"int[]" %7, ptr %z, align 8 + %8 = getelementptr inbounds %"int[]", ptr %vararg1, i32 0, i32 1 + %9 = getelementptr inbounds %"int[]", ptr %vararg1, i32 0, i32 0 + store i64 3, ptr %8, align 8 + store ptr %x, ptr %9, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg2, ptr align 8 %vararg1, i32 16, i1 false) + %10 = call i32 @sum_us(ptr %indirectarg2) + %11 = getelementptr inbounds %"int[]", ptr %vararg3, i32 0, i32 1 + %12 = getelementptr inbounds %"int[]", ptr %vararg3, i32 0, i32 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg4, ptr align 8 %z, i32 16, i1 false) + %13 = call i32 @sum_us(ptr %indirectarg4) + %14 = getelementptr inbounds %"int[]", ptr %vararg5, i32 0, i32 1 + store i64 0, ptr %14, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg6, ptr align 8 %vararg5, i32 16, i1 false) + %15 = call i32 @sum_us(ptr %indirectarg6) + ret void diff --git a/test/test_suite2/functions/static_vars.c3t b/test/test_suite2/functions/static_vars.c3t new file mode 100644 index 000000000..2bf713c6a --- /dev/null +++ b/test/test_suite2/functions/static_vars.c3t @@ -0,0 +1,22 @@ +module foo; + +fn int test() +{ + static int x = 1; + tlocal int y = 2; + x++; + return x; +} + +// #expect: foo.ll + +@test.x = internal unnamed_addr global i32 1, align 4 +@test.y = internal thread_local(localdynamic) unnamed_addr global i32 2, align 4 + +define i32 @foo.test() + + %0 = load i32, ptr @test.x, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr @test.x, align 4 + %1 = load i32, ptr @test.x, align 4 + ret i32 %1 diff --git a/test/test_suite2/functions/test_regression.c3t b/test/test_suite2/functions/test_regression.c3t new file mode 100644 index 000000000..e2579ad87 --- /dev/null +++ b/test/test_suite2/functions/test_regression.c3t @@ -0,0 +1,678 @@ +// #target: macos-x64 + +module test; +import test2; +import std::array::list; +import std::array::linkedlist; +import hello_world; + + +extern fn int printf(char *, ...); + +fn void helloWorld() +{ + printf("helloWorld!\n"); +} +fn int test_static() +{ + static int x = 1; + x++; + printf("Test static %d\n", x); + return x; +} + +struct Bobo { short b; float c; short d; short e; float f; short g; } + + +struct Blob { int z; int f; } + +union Foor +{ + long a; + char[12] b; +} + + +fn int helo(double d, Bobo b) +{ + int[3] de = { 1, 2, 3 }; + Bobo c = b; + helo(1.0, c); + return 1; +} + + +fn int test1(int a, int b) +{ + a = a >> b; + if (b > 128) return -1; + return a; +} + +struct Foo2 +{ + int x; +} + +fn void Foo2.printme(Foo2 *foo) +{ + printf("Foo is: %d\n", foo.x); +} + +fn int Foo2.mutate(Foo2 *foo) +{ + printf("Mutating"); + return ++foo.x; +} + +define oopsInt = test2::argh; +define oopsDouble = test2::argh; +define Argh = fn int(double, Bobo); +define Argh2 = fn int(double, Bobo); + + + +fn int sum_us(int... x) +{ + int sum = 0; + if (x.len == 0) return 0; + sum += x[0] + sum_us(...x[1..^1]); + return sum; +} + +define Frob = long; + +fn int sumd(int[] x) +{ + int sum = 0; + for (int i = 0; i < x.len; i++) sum += x[i]; + return sum; +} + +struct Foo +{ + int a; + int b; +} + +define getValueInt = test2::getValue; +define getValueDouble = test2::getValue; +define IntBlob = test2::Blob; +define DoubleBlob = Blob; +define getMultInt = test2::getMult; +define getMultDouble = test2::getMult; + +define IntArray = List; +define IntList = LinkedList; + +enum MyEnum : int +{ + HELO, + WORLD, + BYE +} + + +fn void main() +{ + test_static(); + test_static(); + test_static(); + hello_world::hello(); + IntList list; + list.push(10); + list.push(15); + list.push(30); + for (int i = 0; i < (int)(list.len()); i++) + { + printf("Element[%d]: %d\n", i, list.get(i)); + } + list.free(); + + printf("Elements: %d\n", (int)(MyEnum.elements)); + + int elements = MyEnum.elements; + printf("Hello\n"); + IntArray array; + array.append(100); + array.append(200); + array.append(400); + array.push(600); + array.insertAt(2, 300); + for (int i = 0; i < (int)(array.len()); i++) + { + printf("Element[%d]: %d\n", i, array.get(i)); + } + array.free(); + IntBlob a = { 42 }; + DoubleBlob b = { 33.3 }; + printf("a was %d\n", getValueInt(a)); + printf("b was %f\n", getValueDouble(b)); + printf("Mult int was %d\n", getMultInt(25)); + printf("Mult double was %f\n", getMultDouble(3.3)); + + + helloWorld(); + Foo ddx; + int fro = 3; + int[4] x = { 1, 2, 3, 3 }; + fro += printf("1Vararg4unsplatA: %d\n", sum_us(...x)); + printf("%d\n", fro); + int[] z = &x; + int[3] de = { 1, 2, 3 }; + printf("Vararg4unsplatB: %d\n", sum_us(...&x)); + printf("Vararg4unsplatC: %d\n", sum_us(...z)); + printf("Vararg4: %d\n", sum_us(1, 2, 4, 5)); + printf("Vararg1: %d\n", sum_us(1)); + printf("Vararg0: %d\n", sum_us()); + Argh a1; + Argh2 b2; +} + +module hello_world; +import foo; + +extern fn int printf(char *, ...); +define doubleMult = foo::check; + +fn void hello() +{ + printf("Hello baby\n"); + printf("Mult %f\n", doubleMult(11.1)); +} + +module foo ; + +fn Type check(Type i) +{ + return i * i; +} + +module test2 ; + +struct Blob +{ + Type a; +} + +fn Type getMult(Type a) +{ + return a * a; +} +Type argh = 234; + +fault MyErr +{ + X, + Y +} + +enum Hello : int +{ + FOO, + BAR, +} + +macro Hello wut() +{ + return Hello.FOO; +} + +define Bye = Hello; +define wat = wut; +define byebye = hello; + +fn int hello() +{ + return 1; +} + +fn Type getValue(Blob blob) +{ + return blob.a; +} + +/* #expect: test.ll + +%Blob = type { i32 } +%Blob.0 = type { double } +%Foo2 = type { i32 } +%Bobo = type { i16, float, i16, i16, float, i16 } +%"int[]" = type { ptr, i64 } +%LinkedList = type { i64, ptr, ptr } +%List = type { i64, i64, ptr } +%Foo = type { i32, i32 } + +@.typeid.test.Bobo = linkonce constant { i8, i64 } { i8 10, i64 6 }, align 8 +@.typeid.test.Blob = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.typeid.test.Foor = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.test.Foo2 = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8 +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.typeid.test.MyEnum = linkonce constant { i8, i64, i64 } { i8 8, i64 3, i64 0 }, align 8 + +define void @test.Foo2__printme(ptr %0) #0 { +entry: + %1 = getelementptr inbounds %Foo2, ptr %0, i32 0, i32 0 + %2 = load i32, ptr %1, align 8 + %3 = call i32 (ptr, ...) @printf(ptr @.str.21, i32 %2) + ret void +} + +; Function Attrs: nounwind +define i32 @test.Foo2__mutate(ptr %0) #0 { +entry: + %1 = call i32 (ptr, ...) @printf(ptr @.str.22) + %2 = getelementptr inbounds %Foo2, ptr %0, i32 0, i32 0 + %3 = load i32, ptr %2, align 8 + %add = add i32 %3, 1 + store i32 %add, ptr %2, align 8 + ret i32 %add +} + +; Function Attrs: nounwind +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @test.helloWorld() #0 { +entry: + %0 = call i32 (ptr, ...) @printf(ptr @.str) + ret void +} + +; Function Attrs: nounwind +define i32 @test.test_static() #0 { +entry: + %0 = load i32, ptr @test_static.x, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr @test_static.x, align 4 + %1 = load i32, ptr @test_static.x, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %1) + %3 = load i32, ptr @test_static.x, align 4 + ret i32 %3 +} + +; Function Attrs: nounwind +define i32 @test.helo(double %0, ptr byval(%Bobo) align 8 %1) #0 { +entry: + %b = alloca %Bobo, align 4 + %de = alloca [3 x i32], align 4 + %c = alloca %Bobo, align 4 + %indirectarg = alloca %Bobo, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 8 %1, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %de, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %c, ptr align 4 %b, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 4 %c, i32 20, i1 false) + %2 = call i32 @test.helo(double 1.000000e+00, ptr byval(%Bobo) align 8 %indirectarg) + ret i32 1 +} + +; Function Attrs: nounwind +define i32 @test.test1(i32 %0, i32 %1) #0 { +entry: + %a = alloca i32, align 4 + store i32 %0, ptr %a, align 4 + %2 = load i32, ptr %a, align 4 + %ashr = ashr i32 %2, %1 + %3 = freeze i32 %ashr + store i32 %3, ptr %a, align 4 + %gt = icmp sgt i32 %1, 128 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i32 -1 + +if.exit: ; preds = %entry + %4 = load i32, ptr %a, align 4 + ret i32 %4 +} + +; Function Attrs: nounwind +define i32 @test.sum_us(ptr %0, i64 %1) #0 { +entry: + %x = alloca %"int[]", align 8 + %sum = alloca i32, align 4 + %vararg = alloca %"int[]", align 8 + %taddr = alloca %"int[]", align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %x, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %x, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + store i32 0, ptr %sum, align 4 + %4 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + %eq = icmp eq i64 0, %5 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i32 0 + +if.exit: ; preds = %entry + %6 = load i32, ptr %sum, align 4 + %7 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + %ptroffset = getelementptr inbounds i32, ptr %8, i64 0 + %9 = load i32, ptr %ptroffset, align 4 + %10 = load %"int[]", ptr %x, align 8 + %11 = extractvalue %"int[]" %10, 0 + %12 = extractvalue %"int[]" %10, 1 + %sub = sub i64 %12, 1 + %13 = add i64 %sub, 1 + %size = sub i64 %13, 1 + %ptroffset1 = getelementptr inbounds i32, ptr %11, i64 1 + %14 = insertvalue %"int[]" undef, ptr %ptroffset1, 0 + %15 = insertvalue %"int[]" %14, i64 %size, 1 + %16 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 1 + %17 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 0 + store %"int[]" %15, ptr %taddr, align 8 + %18 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 + %lo = load ptr, ptr %18, align 8 + %19 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 + %hi = load i64, ptr %19, align 8 + %20 = call i32 @test.sum_us(ptr %lo, i64 %hi) + %add = add i32 %9, %20 + %add2 = add i32 %6, %add + store i32 %add2, ptr %sum, align 4 + %21 = load i32, ptr %sum, align 4 + ret i32 %21 +} + +; Function Attrs: nounwind +define i32 @test.sumd(ptr %0, i64 %1) #0 { +entry: + %x = alloca %"int[]", align 8 + %sum = alloca i32, align 4 + %i = alloca i32, align 4 + %2 = getelementptr inbounds { ptr, i64 }, ptr %x, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %x, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + store i32 0, ptr %sum, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %4 = load i32, ptr %i, align 4 + %sisiext = sext i32 %4 to i64 + %5 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 1 + %6 = load i64, ptr %5, align 8 + %lt = icmp slt i64 %sisiext, %6 + %check = icmp slt i64 %6, 0 + %siui-lt = or i1 %check, %lt + br i1 %siui-lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %7 = load i32, ptr %sum, align 4 + %8 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 0 + %9 = load ptr, ptr %8, align 8 + %10 = load i32, ptr %i, align 4 + %sisiext1 = sext i32 %10 to i64 + %ptroffset = getelementptr inbounds i32, ptr %9, i64 %sisiext1 + %11 = load i32, ptr %ptroffset, align 4 + %add = add i32 %7, %11 + store i32 %add, ptr %sum, align 4 + %12 = load i32, ptr %i, align 4 + %add2 = add i32 %12, 1 + store i32 %add2, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %13 = load i32, ptr %sum, align 4 + ret i32 %13 +} + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %list = alloca %LinkedList, align 8 + %i = alloca i32, align 4 + %elements = alloca i32, align 4 + %array = alloca %List, align 8 + %i1 = alloca i32, align 4 + %a = alloca %Blob, align 4 + %b = alloca %Blob.0, align 8 + %tempcoerce = alloca double, align 8 + %ddx = alloca %Foo, align 4 + %fro = alloca i32, align 4 + %x = alloca [4 x i32], align 16 + %vararg = alloca %"int[]", align 8 + %z = alloca %"int[]", align 8 + %de = alloca [3 x i32], align 4 + %vararg10 = alloca %"int[]", align 8 + %vararg13 = alloca %"int[]", align 8 + %vararg16 = alloca %"int[]", align 8 + %varargslots = alloca [4 x i32], align 16 + %vararg19 = alloca %"int[]", align 8 + %varargslots20 = alloca [1 x i32], align 4 + %vararg23 = alloca %"int[]", align 8 + %a1 = alloca ptr, align 8 + %b2 = alloca ptr, align 8 + %0 = call i32 @test.test_static() + %1 = call i32 @test.test_static() + %2 = call i32 @test.test_static() + call void @hello_world.hello() + call void @llvm.memset.p0.i64(ptr align 8 %list, i8 0, i64 24, i1 false) + call void @"std::array::linkedlist.int.LinkedList__push"(ptr %list, i32 10) + call void @"std::array::linkedlist.int.LinkedList__push"(ptr %list, i32 15) + call void @"std::array::linkedlist.int.LinkedList__push"(ptr %list, i32 30) + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %3 = load i32, ptr %i, align 4 + %4 = call i64 @"std::array::linkedlist.int.LinkedList__len"(ptr %list) #3 + %uisitrunc = trunc i64 %4 to i32 + %lt = icmp slt i32 %3, %uisitrunc + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %5 = load i32, ptr %i, align 4 + %6 = load i32, ptr %i, align 4 + %siuiext = sext i32 %6 to i64 + %7 = call i32 @"std::array::linkedlist.int.LinkedList__get"(ptr %list, i64 %siuiext) + %8 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %5, i32 %7) + %9 = load i32, ptr %i, align 4 + %add = add i32 %9, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + call void @"std::array::linkedlist.int.LinkedList__free"(ptr %list) + %10 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 3) + store i32 3, ptr %elements, align 4 + %11 = call i32 (ptr, ...) @printf(ptr @.str.4) + call void @llvm.memset.p0.i64(ptr align 8 %array, i8 0, i64 24, i1 false) + call void @"std::array::list.int.List__append"(ptr %array, i32 100) + call void @"std::array::list.int.List__append"(ptr %array, i32 200) + call void @"std::array::list.int.List__append"(ptr %array, i32 400) + call void @"std::array::list.int.List__push"(ptr %array, i32 600) #3 + call void @"std::array::list.int.List__insertAt"(ptr %array, i64 2, i32 300) + store i32 0, ptr %i1, align 4 + br label %loop.cond2 + +loop.cond2: ; preds = %loop.body5, %loop.exit + %12 = load i32, ptr %i1, align 4 + %13 = call i64 @"std::array::list.int.List__len"(ptr %array) + %uisitrunc3 = trunc i64 %13 to i32 + %lt4 = icmp slt i32 %12, %uisitrunc3 + br i1 %lt4, label %loop.body5, label %loop.exit8 + +loop.body5: ; preds = %loop.cond2 + %14 = load i32, ptr %i1, align 4 + %15 = load i32, ptr %i1, align 4 + %siuiext6 = sext i32 %15 to i64 + %16 = call i32 @"std::array::list.int.List__get"(ptr %array, i64 %siuiext6) + %17 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %14, i32 %16) + %18 = load i32, ptr %i1, align 4 + %add7 = add i32 %18, 1 + store i32 %add7, ptr %i1, align 4 + br label %loop.cond2 + +loop.exit8: ; preds = %loop.cond2 + call void @"std::array::list.int.List__free"(ptr %array) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a, ptr align 4 @.__const.6, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %b, ptr align 8 @.__const.7, i32 8, i1 false) + %19 = getelementptr inbounds %Blob, ptr %a, i32 0, i32 0 + %20 = load i32, ptr %19, align 4 + %21 = call i32 @test2.int.getValue(i32 %20) + %22 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %21) + %23 = getelementptr inbounds %Blob.0, ptr %b, i32 0, i32 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %23, i32 8, i1 false) + %24 = load double, ptr %tempcoerce, align 8 + %25 = call double @test2.double.getValue(double %24) + %26 = call i32 (ptr, ...) @printf(ptr @.str.9, double %25) + %27 = call i32 @test2.int.getMult(i32 25) + %28 = call i32 (ptr, ...) @printf(ptr @.str.10, i32 %27) + %29 = call double @test2.double.getMult(double 3.300000e+00) + %30 = call i32 (ptr, ...) @printf(ptr @.str.11, double %29) + call void @test.helloWorld() + %31 = getelementptr inbounds %Foo, ptr %ddx, i32 0, i32 0 + store i32 0, ptr %31, align 4 + %32 = getelementptr inbounds %Foo, ptr %ddx, i32 0, i32 1 + store i32 0, ptr %32, align 4 + store i32 3, ptr %fro, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 16 @.__const.12, i32 16, i1 false) + %33 = load i32, ptr %fro, align 4 + %34 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 1 + %35 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 0 + store i64 4, ptr %34, align 8 + store ptr %x, ptr %35, align 8 + %36 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo = load ptr, ptr %36, align 8 + %37 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi = load i64, ptr %37, align 8 + %38 = call i32 @test.sum_us(ptr %lo, i64 %hi) + %39 = call i32 (ptr, ...) @printf(ptr @.str.13, i32 %38) + %add9 = add i32 %33, %39 + store i32 %add9, ptr %fro, align 4 + %40 = load i32, ptr %fro, align 4 + %41 = call i32 (ptr, ...) @printf(ptr @.str.14, i32 %40) + %42 = insertvalue %"int[]" undef, ptr %x, 0 + %43 = insertvalue %"int[]" %42, i64 4, 1 + store %"int[]" %43, ptr %z, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %de, ptr align 4 @.__const.15, i32 12, i1 false) + %44 = getelementptr inbounds %"int[]", ptr %vararg10, i32 0, i32 1 + %45 = getelementptr inbounds %"int[]", ptr %vararg10, i32 0, i32 0 + store i64 4, ptr %44, align 8 + store ptr %x, ptr %45, align 8 + %46 = getelementptr inbounds { ptr, i64 }, ptr %vararg10, i32 0, i32 0 + %lo11 = load ptr, ptr %46, align 8 + %47 = getelementptr inbounds { ptr, i64 }, ptr %vararg10, i32 0, i32 1 + %hi12 = load i64, ptr %47, align 8 + %48 = call i32 @test.sum_us(ptr %lo11, i64 %hi12) + %49 = call i32 (ptr, ...) @printf(ptr @.str.16, i32 %48) + %50 = getelementptr inbounds %"int[]", ptr %vararg13, i32 0, i32 1 + %51 = getelementptr inbounds %"int[]", ptr %vararg13, i32 0, i32 0 + %52 = getelementptr inbounds { ptr, i64 }, ptr %z, i32 0, i32 0 + %lo14 = load ptr, ptr %52, align 8 + %53 = getelementptr inbounds { ptr, i64 }, ptr %z, i32 0, i32 1 + %hi15 = load i64, ptr %53, align 8 + %54 = call i32 @test.sum_us(ptr %lo14, i64 %hi15) + %55 = call i32 (ptr, ...) @printf(ptr @.str.17, i32 %54) + %56 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 0 + store i32 1, ptr %56, align 4 + %57 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 1 + store i32 2, ptr %57, align 4 + %58 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 2 + store i32 4, ptr %58, align 4 + %59 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 3 + store i32 5, ptr %59, align 4 + %60 = getelementptr inbounds %"int[]", ptr %vararg16, i32 0, i32 1 + store i64 4, ptr %60, align 8 + %61 = getelementptr inbounds %"int[]", ptr %vararg16, i32 0, i32 0 + store ptr %varargslots, ptr %61, align 8 + %62 = getelementptr inbounds { ptr, i64 }, ptr %vararg16, i32 0, i32 0 + %lo17 = load ptr, ptr %62, align 8 + %63 = getelementptr inbounds { ptr, i64 }, ptr %vararg16, i32 0, i32 1 + %hi18 = load i64, ptr %63, align 8 + %64 = call i32 @test.sum_us(ptr %lo17, i64 %hi18) + %65 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %64) + %66 = getelementptr inbounds [1 x i32], ptr %varargslots20, i64 0, i64 0 + store i32 1, ptr %66, align 4 + %67 = getelementptr inbounds %"int[]", ptr %vararg19, i32 0, i32 1 + store i64 1, ptr %67, align 8 + %68 = getelementptr inbounds %"int[]", ptr %vararg19, i32 0, i32 0 + store ptr %varargslots20, ptr %68, align 8 + %69 = getelementptr inbounds { ptr, i64 }, ptr %vararg19, i32 0, i32 0 + %lo21 = load ptr, ptr %69, align 8 + %70 = getelementptr inbounds { ptr, i64 }, ptr %vararg19, i32 0, i32 1 + %hi22 = load i64, ptr %70, align 8 + %71 = call i32 @test.sum_us(ptr %lo21, i64 %hi22) + %72 = call i32 (ptr, ...) @printf(ptr @.str.19, i32 %71) + %73 = getelementptr inbounds %"int[]", ptr %vararg23, i32 0, i32 1 + store i64 0, ptr %73, align 8 + %74 = getelementptr inbounds { ptr, i64 }, ptr %vararg23, i32 0, i32 0 + %lo24 = load ptr, ptr %74, align 8 + %75 = getelementptr inbounds { ptr, i64 }, ptr %vararg23, i32 0, i32 1 + %hi25 = load i64, ptr %75, align 8 + %76 = call i32 @test.sum_us(ptr %lo24, i64 %hi25) + %77 = call i32 (ptr, ...) @printf(ptr @.str.20, i32 %76) + store ptr null, ptr %a1, align 8 + store ptr null, ptr %b2, align 8 + ret void +} + +// #expect: hello_world.ll + +define void @hello_world.hello() +entry: + %0 = call i32 (ptr, ...) @printf(ptr @.str) + %1 = call double @foo.double.check(double 1.110000e+01) + %2 = call i32 (ptr, ...) @printf(ptr @.str.1, double %1) + ret void + +// #expect: foo.double.ll + +define double @foo.double.check(double %0) +entry: + %fmul = fmul double %0, %0 + ret double %fmul + + +// #expect: test2.int.ll + +%Blob = type { i32 } +@test2.int.argh = local_unnamed_addr global i32 234, align 4 + +define i32 @test2.int.getMult(i32 %0) #0 { +entry: + %mul = mul i32 %0, %0 + ret i32 %mul +} + +define i32 @test2.int.hello() #0 { +entry: + ret i32 1 +} + +define i32 @test2.int.getValue(i32 %0) #0 { +entry: + %blob = alloca %Blob, align 4 + %1 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + store i32 %0, ptr %1, align 4 + %2 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + %3 = load i32, ptr %2, align 4 + ret i32 %3 +} + +// #expect: test2.double.ll + +%Blob = type { double } +@test2.double.argh = local_unnamed_addr global double 2.340000e+02, align 8 + +define double @test2.double.getMult(double %0) +entry: + %fmul = fmul double %0, %0 + ret double %fmul + +define i32 @test2.double.hello() +entry: + ret i32 1 + +define double @test2.double.getValue(double %0) +entry: + %blob = alloca %Blob, align 8 + %1 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + store double %0, ptr %1, align 8 + %2 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + %3 = load double, ptr %2, align 8 + ret double %3 \ No newline at end of file diff --git a/test/test_suite2/functions/test_regression_mingw.c3t b/test/test_suite2/functions/test_regression_mingw.c3t new file mode 100644 index 000000000..667128d3e --- /dev/null +++ b/test/test_suite2/functions/test_regression_mingw.c3t @@ -0,0 +1,731 @@ +// #target: mingw-x64 + +module test; +import test2; +import std::array::list; +import std::array::linkedlist; +import hello_world; + + +extern fn int printf(char *, ...); + +fn void helloWorld() +{ + printf("helloWorld!\n"); +} +fn int test_static() +{ + static int x = 1; + x++; + printf("Test static %d\n", x); + return x; +} + +struct Bobo { short b; float c; short d; short e; float f; short g; } + + +struct Blob { int z; int f; } + +union Foor +{ + long a; + char[12] b; +} + + +fn int helo(double d, Bobo b) +{ + int[3] de = { 1, 2, 3 }; + Bobo c = b; + helo(1.0, c); + return 1; +} + + +fn int test1(int a, int b) +{ + a = a >> b; + if (b > 128) return -1; + return a; +} + +struct Foo2 +{ + int x; +} + +fn void Foo2.printme(Foo2 *foo) +{ + printf("Foo is: %d\n", foo.x); +} + +fn int Foo2.mutate(Foo2 *foo) +{ + printf("Mutating"); + return ++foo.x; +} + + + +define oopsInt = test2::argh; +define oopsDouble = test2::argh; +define Argh = fn int(double, Bobo); +define Argh2 = fn int(double, Bobo); + + + +fn int sum_us(int... x) +{ + int sum = 0; + if (x.len == 0) return 0; + sum += x[0] + sum_us(...x[1..^1]); + return sum; +} + +define Frob = long; + +fn int sumd(int[] x) +{ + int sum = 0; + for (int i = 0; i < x.len; i++) sum += x[i]; + return sum; +} + +struct Foo +{ + int a; + int b; +} + +define getValueInt = test2::getValue; +define getValueDouble = test2::getValue; +define IntBlob = test2::Blob; +define DoubleBlob = Blob; +define getMultInt = test2::getMult; +define getMultDouble = test2::getMult; + +define IntArray = List; +define IntList = LinkedList; + +enum MyEnum : int +{ + HELO, + WORLD, + BYE +} + + +fn void main() +{ + test_static(); + test_static(); + test_static(); + hello_world::hello(); + IntList list; + list.push(10); + list.push(15); + list.push(30); + for (int i = 0; i < (int)(list.len()); i++) + { + printf("Element[%d]: %d\n", i, list.get(i)); + } + list.free(); + + printf("Elements: %d\n", (int)(MyEnum.elements)); + + int elements = MyEnum.elements; + printf("Hello\n"); + IntArray array; + array.append(100); + array.append(200); + array.append(400); + array.push(600); + array.insertAt(2, 300); + for (int i = 0; i < (int)(array.len()); i++) + { + printf("Element[%d]: %d\n", i, array.get(i)); + } + array.free(); + IntBlob a = { 42 }; + DoubleBlob b = { 33.3 }; + printf("a was %d\n", getValueInt(a)); + printf("b was %f\n", getValueDouble(b)); + printf("Mult int was %d\n", getMultInt(25)); + printf("Mult double was %f\n", getMultDouble(3.3)); + + + helloWorld(); + Foo ddx; + int fro = 3; + int[4] x = { 1, 2, 3, 3 }; + fro += printf("1Vararg4unsplatA: %d\n", sum_us(...x)); + printf("%d\n", fro); + int[] z = &x; + int[3] de = { 1, 2, 3 }; + printf("Vararg4unsplatB: %d\n", sum_us(...&x)); + printf("Vararg4unsplatC: %d\n", sum_us(...z)); + printf("Vararg4: %d\n", sum_us(1, 2, 4, 5)); + printf("Vararg1: %d\n", sum_us(1)); + printf("Vararg0: %d\n", sum_us()); + Argh a1; + Argh2 b2; +} + +module hello_world; +import foo; + +extern fn int printf(char *, ...); +define doubleMult = foo::check; + +fn void hello() +{ + printf("Hello baby\n"); + printf("Mult %f\n", doubleMult(11.1)); +} + +module foo ; + +fn Type check(Type i) +{ + return i * i; +} + +module test2 ; + +struct Blob +{ + Type a; +} + +fn Type getMult(Type a) +{ + return a * a; +} +Type argh = 234; + +fault MyErr +{ + X, + Y +} + +enum Hello : int +{ + FOO, + BAR, +} + +macro Hello wut() +{ + return Hello.FOO; +} + +define Bye = Hello; +define wat = wut; +define byebye = hello; + +fn int hello() +{ + return 1; +} + +fn Type getValue(Blob blob) +{ + return blob.a; +} + +/* #expect: test.ll + +%Blob = type { i32 } +%Blob.0 = type { double } +%Foo2 = type { i32 } +%Bobo = type { i16, float, i16, i16, float, i16 } +%"int[]" = type { ptr, i64 } +%LinkedList = type { i64, ptr, ptr } +%List = type { i64, i64, ptr } +%Foo = type { i32, i32 } + +$.typeid.test.Bobo = comdat any + +$.typeid.test.Blob = comdat any + +$.typeid.test.Foor = comdat any + +$.typeid.test.Foo2 = comdat any + +$.typeid.test.Foo = comdat any + +$.typeid.test.MyEnum = comdat any + +@.typeid.test.Bobo = linkonce constant { i8, i64 } { i8 10, i64 6 }, comdat, align 8 +@.typeid.test.Blob = linkonce constant { i8, i64 } { i8 10, i64 2 }, comdat, align 8 +@.typeid.test.Foor = linkonce constant { i8, i64 } { i8 11, i64 2 }, comdat, align 8 +@.typeid.test.Foo2 = linkonce constant { i8, i64 } { i8 10, i64 1 }, comdat, align 8 +@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, comdat, align 8 +@.typeid.test.MyEnum = linkonce constant { i8, i64, i64 } { i8 8, i64 3, i64 0 }, comdat, align 8 +@.str = private unnamed_addr constant [13 x i8] c"helloWorld!\0A\00", align 1 +@test_static.x = internal unnamed_addr global i32 1, align 4 +@.str.1 = private unnamed_addr constant [16 x i8] c"Test static %d\0A\00", align 1 +@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@.str.2 = private unnamed_addr constant [17 x i8] c"Element[%d]: %d\0A\00", align 1 +@.str.3 = private unnamed_addr constant [14 x i8] c"Elements: %d\0A\00", align 1 +@.str.4 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1 +@.str.5 = private unnamed_addr constant [17 x i8] c"Element[%d]: %d\0A\00", align 1 +@.__const.6 = private unnamed_addr constant %Blob { i32 42 }, align 4 +@.__const.7 = private unnamed_addr constant %Blob.0 { double 3.330000e+01 }, align 8 +@.str.8 = private unnamed_addr constant [10 x i8] c"a was %d\0A\00", align 1 +@.str.9 = private unnamed_addr constant [10 x i8] c"b was %f\0A\00", align 1 +@.str.10 = private unnamed_addr constant [17 x i8] c"Mult int was %d\0A\00", align 1 +@.str.11 = private unnamed_addr constant [20 x i8] c"Mult double was %f\0A\00", align 1 +@.__const.12 = private unnamed_addr constant [4 x i32] [i32 1, i32 2, i32 3, i32 3], align 16 +@.str.13 = private unnamed_addr constant [22 x i8] c"1Vararg4unsplatA: %d\0A\00", align 1 +@.str.14 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@.__const.15 = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@.str.16 = private unnamed_addr constant [21 x i8] c"Vararg4unsplatB: %d\0A\00", align 1 +@.str.17 = private unnamed_addr constant [21 x i8] c"Vararg4unsplatC: %d\0A\00", align 1 +@.str.18 = private unnamed_addr constant [13 x i8] c"Vararg4: %d\0A\00", align 1 +@.str.19 = private unnamed_addr constant [13 x i8] c"Vararg1: %d\0A\00", align 1 +@.str.20 = private unnamed_addr constant [13 x i8] c"Vararg0: %d\0A\00", align 1 +@.str.21 = private unnamed_addr constant [12 x i8] c"Foo is: %d\0A\00", align 1 +@.str.22 = private unnamed_addr constant [9 x i8] c"Mutating\00", align 1 + +; Function Attrs: nounwind +define void @test.Foo2__printme(ptr %0) #0 { +entry: + %1 = getelementptr inbounds %Foo2, ptr %0, i32 0, i32 0 + %2 = load i32, ptr %1, align 8 + %3 = call i32 (ptr, ...) @printf(ptr @.str.21, i32 %2) + ret void +} + +; Function Attrs: nounwind +define i32 @test.Foo2__mutate(ptr %0) #0 { +entry: + %1 = call i32 (ptr, ...) @printf(ptr @.str.22) + %2 = getelementptr inbounds %Foo2, ptr %0, i32 0, i32 0 + %3 = load i32, ptr %2, align 8 + %add = add i32 %3, 1 + store i32 %add, ptr %2, align 8 + ret i32 %add +} + +; Function Attrs: nounwind +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @test.helloWorld() #0 { +entry: + %0 = call i32 (ptr, ...) @printf(ptr @.str) + ret void +} + +; Function Attrs: nounwind +define i32 @test.test_static() #0 { +entry: + %0 = load i32, ptr @test_static.x, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr @test_static.x, align 4 + %1 = load i32, ptr @test_static.x, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %1) + %3 = load i32, ptr @test_static.x, align 4 + ret i32 %3 +} + +; Function Attrs: nounwind +define i32 @test.helo(double %0, ptr align 4 %1) #0 { +entry: + %b = alloca %Bobo, align 4 + %de = alloca [3 x i32], align 4 + %c = alloca %Bobo, align 4 + %indirectarg = alloca %Bobo, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 4 %1, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %de, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %c, ptr align 4 %b, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %indirectarg, ptr align 4 %c, i32 20, i1 false) + %2 = call i32 @test.helo(double 1.000000e+00, ptr align 4 %indirectarg) + ret i32 1 +} + +; Function Attrs: nounwind +define i32 @test.test1(i32 %0, i32 %1) #0 { +entry: + %a = alloca i32, align 4 + store i32 %0, ptr %a, align 4 + %2 = load i32, ptr %a, align 4 + %ashr = ashr i32 %2, %1 + %3 = freeze i32 %ashr + store i32 %3, ptr %a, align 4 + %gt = icmp sgt i32 %1, 128 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i32 -1 + +if.exit: ; preds = %entry + %4 = load i32, ptr %a, align 4 + ret i32 %4 +} + +; Function Attrs: nounwind +define i32 @test.sum_us(ptr align 8 %0) #0 { +entry: + %x = alloca %"int[]", align 8 + %sum = alloca i32, align 4 + %vararg = alloca %"int[]", align 8 + %indirectarg = alloca %"int[]", align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x, ptr align 8 %0, i32 16, i1 false) + store i32 0, ptr %sum, align 4 + %1 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 1 + %2 = load i64, ptr %1, align 8 + %eq = icmp eq i64 0, %2 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i32 0 + +if.exit: ; preds = %entry + %3 = load i32, ptr %sum, align 4 + %4 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + %ptroffset = getelementptr inbounds i32, ptr %5, i64 0 + %6 = load i32, ptr %ptroffset, align 4 + %7 = load %"int[]", ptr %x, align 8 + %8 = extractvalue %"int[]" %7, 0 + %9 = extractvalue %"int[]" %7, 1 + %sub = sub i64 %9, 1 + %10 = add i64 %sub, 1 + %size = sub i64 %10, 1 + %ptroffset1 = getelementptr inbounds i32, ptr %8, i64 1 + %11 = insertvalue %"int[]" undef, ptr %ptroffset1, 0 + %12 = insertvalue %"int[]" %11, i64 %size, 1 + %13 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 1 + %14 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 0 + store %"int[]" %12, ptr %indirectarg, align 8 + %15 = call i32 @test.sum_us(ptr %indirectarg) + %add = add i32 %6, %15 + %add2 = add i32 %3, %add + store i32 %add2, ptr %sum, align 4 + %16 = load i32, ptr %sum, align 4 + ret i32 %16 +} + +; Function Attrs: nounwind +define i32 @test.sumd(ptr align 8 %0) #0 { +entry: + %x = alloca %"int[]", align 8 + %sum = alloca i32, align 4 + %i = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x, ptr align 8 %0, i32 16, i1 false) + store i32 0, ptr %sum, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %1 = load i32, ptr %i, align 4 + %sisiext = sext i32 %1 to i64 + %2 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 1 + %3 = load i64, ptr %2, align 8 + %lt = icmp slt i64 %sisiext, %3 + %check = icmp slt i64 %3, 0 + %siui-lt = or i1 %check, %lt + br i1 %siui-lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %4 = load i32, ptr %sum, align 4 + %5 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 0 + %6 = load ptr, ptr %5, align 8 + %7 = load i32, ptr %i, align 4 + %sisiext1 = sext i32 %7 to i64 + %ptroffset = getelementptr inbounds i32, ptr %6, i64 %sisiext1 + %8 = load i32, ptr %ptroffset, align 4 + %add = add i32 %4, %8 + store i32 %add, ptr %sum, align 4 + %9 = load i32, ptr %i, align 4 + %add2 = add i32 %9, 1 + store i32 %add2, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %10 = load i32, ptr %sum, align 4 + ret i32 %10 +} + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %list = alloca %LinkedList, align 8 + %i = alloca i32, align 4 + %elements = alloca i32, align 4 + %array = alloca %List, align 8 + %i1 = alloca i32, align 4 + %a = alloca %Blob, align 4 + %b = alloca %Blob.0, align 8 + %tempcoerce = alloca i64, align 8 + %ddx = alloca %Foo, align 4 + %fro = alloca i32, align 4 + %x = alloca [4 x i32], align 16 + %vararg = alloca %"int[]", align 8 + %indirectarg = alloca %"int[]", align 8 + %z = alloca %"int[]", align 8 + %de = alloca [3 x i32], align 4 + %vararg10 = alloca %"int[]", align 8 + %indirectarg11 = alloca %"int[]", align 8 + %vararg12 = alloca %"int[]", align 8 + %indirectarg13 = alloca %"int[]", align 8 + %vararg14 = alloca %"int[]", align 8 + %varargslots = alloca [4 x i32], align 16 + %indirectarg15 = alloca %"int[]", align 8 + %vararg16 = alloca %"int[]", align 8 + %varargslots17 = alloca [1 x i32], align 4 + %indirectarg18 = alloca %"int[]", align 8 + %vararg19 = alloca %"int[]", align 8 + %indirectarg20 = alloca %"int[]", align 8 + %a1 = alloca ptr, align 8 + %b2 = alloca ptr, align 8 + %0 = call i32 @test.test_static() + %1 = call i32 @test.test_static() + %2 = call i32 @test.test_static() + call void @hello_world.hello() + call void @llvm.memset.p0.i64(ptr align 8 %list, i8 0, i64 24, i1 false) + call void @"std::array::linkedlist.int.LinkedList__push"(ptr %list, i32 10) + call void @"std::array::linkedlist.int.LinkedList__push"(ptr %list, i32 15) + call void @"std::array::linkedlist.int.LinkedList__push"(ptr %list, i32 30) + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %3 = load i32, ptr %i, align 4 + %4 = call i64 @"std::array::linkedlist.int.LinkedList__len"(ptr %list) #3 + %uisitrunc = trunc i64 %4 to i32 + %lt = icmp slt i32 %3, %uisitrunc + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %5 = load i32, ptr %i, align 4 + %6 = load i32, ptr %i, align 4 + %siuiext = sext i32 %6 to i64 + %7 = call i32 @"std::array::linkedlist.int.LinkedList__get"(ptr %list, i64 %siuiext) + %8 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %5, i32 %7) + %9 = load i32, ptr %i, align 4 + %add = add i32 %9, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + call void @"std::array::linkedlist.int.LinkedList__free"(ptr %list) + %10 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 3) + store i32 3, ptr %elements, align 4 + %11 = call i32 (ptr, ...) @printf(ptr @.str.4) + call void @llvm.memset.p0.i64(ptr align 8 %array, i8 0, i64 24, i1 false) + call void @"std::array::list.int.List__append"(ptr %array, i32 100) + call void @"std::array::list.int.List__append"(ptr %array, i32 200) + call void @"std::array::list.int.List__append"(ptr %array, i32 400) + call void @"std::array::list.int.List__push"(ptr %array, i32 600) #3 + call void @"std::array::list.int.List__insertAt"(ptr %array, i64 2, i32 300) + store i32 0, ptr %i1, align 4 + br label %loop.cond2 + +loop.cond2: ; preds = %loop.body5, %loop.exit + %12 = load i32, ptr %i1, align 4 + %13 = call i64 @"std::array::list.int.List__len"(ptr %array) + %uisitrunc3 = trunc i64 %13 to i32 + %lt4 = icmp slt i32 %12, %uisitrunc3 + br i1 %lt4, label %loop.body5, label %loop.exit8 + +loop.body5: ; preds = %loop.cond2 + %14 = load i32, ptr %i1, align 4 + %15 = load i32, ptr %i1, align 4 + %siuiext6 = sext i32 %15 to i64 + %16 = call i32 @"std::array::list.int.List__get"(ptr %array, i64 %siuiext6) + %17 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %14, i32 %16) + %18 = load i32, ptr %i1, align 4 + %add7 = add i32 %18, 1 + store i32 %add7, ptr %i1, align 4 + br label %loop.cond2 + +loop.exit8: ; preds = %loop.cond2 + call void @"std::array::list.int.List__free"(ptr %array) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a, ptr align 4 @.__const.6, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %b, ptr align 8 @.__const.7, i32 8, i1 false) + %19 = getelementptr inbounds %Blob, ptr %a, i32 0, i32 0 + %20 = load i32, ptr %19, align 4 + %21 = call i32 @test2.int.getValue(i32 %20) + %22 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %21) + %23 = getelementptr inbounds %Blob.0, ptr %b, i32 0, i32 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %23, i32 8, i1 false) + %24 = load i64, ptr %tempcoerce, align 8 + %25 = call double @test2.double.getValue(i64 %24) + %26 = call i32 (ptr, ...) @printf(ptr @.str.9, double %25) + %27 = call i32 @test2.int.getMult(i32 25) + %28 = call i32 (ptr, ...) @printf(ptr @.str.10, i32 %27) + %29 = call double @test2.double.getMult(double 3.300000e+00) + %30 = call i32 (ptr, ...) @printf(ptr @.str.11, double %29) + call void @test.helloWorld() + %31 = getelementptr inbounds %Foo, ptr %ddx, i32 0, i32 0 + store i32 0, ptr %31, align 4 + %32 = getelementptr inbounds %Foo, ptr %ddx, i32 0, i32 1 + store i32 0, ptr %32, align 4 + store i32 3, ptr %fro, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 16 @.__const.12, i32 16, i1 false) + %33 = load i32, ptr %fro, align 4 + %34 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 1 + %35 = getelementptr inbounds %"int[]", ptr %vararg, i32 0, i32 0 + store i64 4, ptr %34, align 8 + store ptr %x, ptr %35, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %vararg, i32 16, i1 false) + %36 = call i32 @test.sum_us(ptr %indirectarg) + %37 = call i32 (ptr, ...) @printf(ptr @.str.13, i32 %36) + %add9 = add i32 %33, %37 + store i32 %add9, ptr %fro, align 4 + %38 = load i32, ptr %fro, align 4 + %39 = call i32 (ptr, ...) @printf(ptr @.str.14, i32 %38) + %40 = insertvalue %"int[]" undef, ptr %x, 0 + %41 = insertvalue %"int[]" %40, i64 4, 1 + store %"int[]" %41, ptr %z, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %de, ptr align 4 @.__const.15, i32 12, i1 false) + %42 = getelementptr inbounds %"int[]", ptr %vararg10, i32 0, i32 1 + %43 = getelementptr inbounds %"int[]", ptr %vararg10, i32 0, i32 0 + store i64 4, ptr %42, align 8 + store ptr %x, ptr %43, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg11, ptr align 8 %vararg10, i32 16, i1 false) + %44 = call i32 @test.sum_us(ptr %indirectarg11) + %45 = call i32 (ptr, ...) @printf(ptr @.str.16, i32 %44) + %46 = getelementptr inbounds %"int[]", ptr %vararg12, i32 0, i32 1 + %47 = getelementptr inbounds %"int[]", ptr %vararg12, i32 0, i32 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg13, ptr align 8 %z, i32 16, i1 false) + %48 = call i32 @test.sum_us(ptr %indirectarg13) + %49 = call i32 (ptr, ...) @printf(ptr @.str.17, i32 %48) + %50 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 0 + store i32 1, ptr %50, align 4 + %51 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 1 + store i32 2, ptr %51, align 4 + %52 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 2 + store i32 4, ptr %52, align 4 + %53 = getelementptr inbounds [4 x i32], ptr %varargslots, i64 0, i64 3 + store i32 5, ptr %53, align 4 + %54 = getelementptr inbounds %"int[]", ptr %vararg14, i32 0, i32 1 + store i64 4, ptr %54, align 8 + %55 = getelementptr inbounds %"int[]", ptr %vararg14, i32 0, i32 0 + store ptr %varargslots, ptr %55, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg15, ptr align 8 %vararg14, i32 16, i1 false) + %56 = call i32 @test.sum_us(ptr %indirectarg15) + %57 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %56) + %58 = getelementptr inbounds [1 x i32], ptr %varargslots17, i64 0, i64 0 + store i32 1, ptr %58, align 4 + %59 = getelementptr inbounds %"int[]", ptr %vararg16, i32 0, i32 1 + store i64 1, ptr %59, align 8 + %60 = getelementptr inbounds %"int[]", ptr %vararg16, i32 0, i32 0 + store ptr %varargslots17, ptr %60, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg18, ptr align 8 %vararg16, i32 16, i1 false) + %61 = call i32 @test.sum_us(ptr %indirectarg18) + %62 = call i32 (ptr, ...) @printf(ptr @.str.19, i32 %61) + %63 = getelementptr inbounds %"int[]", ptr %vararg19, i32 0, i32 1 + store i64 0, ptr %63, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg20, ptr align 8 %vararg19, i32 16, i1 false) + %64 = call i32 @test.sum_us(ptr %indirectarg20) + %65 = call i32 (ptr, ...) @printf(ptr @.str.20, i32 %64) + store ptr null, ptr %a1, align 8 + store ptr null, ptr %b2, align 8 + ret void +} + +declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #1 + +declare void @hello_world.hello() + +declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #2 + +declare void @"std::array::linkedlist.int.LinkedList__push"(ptr, i32) + +declare i64 @"std::array::linkedlist.int.LinkedList__len"(ptr) + +declare i32 @"std::array::linkedlist.int.LinkedList__get"(ptr, i64) + +declare void @"std::array::linkedlist.int.LinkedList__free"(ptr) + +declare void @"std::array::list.int.List__append"(ptr, i32) + +declare void @"std::array::list.int.List__push"(ptr, i32) + +declare void @"std::array::list.int.List__insertAt"(ptr, i64, i32) + +declare i64 @"std::array::list.int.List__len"(ptr) + +declare i32 @"std::array::list.int.List__get"(ptr, i64) + +declare void @"std::array::list.int.List__free"(ptr) + +declare i32 @test2.int.getValue(i32) + +declare double @test2.double.getValue(i64) + +declare i32 @test2.int.getMult(i32) + +declare double @test2.double.getMult(double) + +// #expect: hello_world.ll + +define void @hello_world.hello() +entry: + %0 = call i32 (ptr, ...) @printf(ptr @.str) + %1 = call double @foo.double.check(double 1.110000e+01) + %2 = call i32 (ptr, ...) @printf(ptr @.str.1, double %1) + ret void + +// #expect: foo.double.ll + +define double @foo.double.check(double %0) +entry: + %fmul = fmul double %0, %0 + ret double %fmul + + +// #expect: test2.int.ll + +%Blob = type { i32 } +@test2.int.argh = local_unnamed_addr global i32 234, align 4 + +define i32 @test2.int.getMult(i32 %0) +entry: + %mul = mul i32 %0, %0 + ret i32 %mul + +define i32 @test2.int.hello() +entry: + ret i32 1 +} + +define i32 @test2.int.getValue(i32 %0) +entry: + %blob = alloca %Blob, align 4 + %1 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + store i32 %0, ptr %1, align 4 + %2 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + %3 = load i32, ptr %2, align 4 + ret i32 %3 + + +// #expect: test2.double.ll + +%Blob = type { double } +@test2.double.argh = local_unnamed_addr global double 2.340000e+02, align 8 + +define double @test2.double.getMult(double %0) +entry: + %fmul = fmul double %0, %0 + ret double %fmul + + +define i32 @test2.double.hello() +entry: + ret i32 1 + +define double @test2.double.getValue(i64 %0) +entry: + %blob = alloca %Blob, align 8 + %1 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + store i64 %0, ptr %1, align 8 + %2 = getelementptr inbounds %Blob, ptr %blob, i32 0, i32 0 + %3 = load double, ptr %2, align 8 + ret double %3 + diff --git a/test/test_suite2/functions/typeless_varargs.c3t b/test/test_suite2/functions/typeless_varargs.c3t new file mode 100644 index 000000000..e15d23870 --- /dev/null +++ b/test/test_suite2/functions/typeless_varargs.c3t @@ -0,0 +1,101 @@ +// #target: macos-x64 + +module test; + +extern fn void printf(char*, ...); + +fn void retest(foo...) +{ + test(...foo); +} +fn void test(foo...) +{ + printf("Foo1 was: %d\n", *((int*)foo[0])); +} +fn int main() +{ + int i = 1; + test(1); + retest(1); + return 1; +} + +/* #expect: test.ll + +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 + +define void @test.retest(ptr %0, i64 %1) #0 { +entry: + %foo = alloca %"variant[]", align 8 + %vararg = alloca %"variant[]", align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %foo, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %foo, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + %4 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + %5 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + %6 = getelementptr inbounds { ptr, i64 }, ptr %foo, i32 0, i32 0 + %lo = load ptr, ptr %6, align 8 + %7 = getelementptr inbounds { ptr, i64 }, ptr %foo, i32 0, i32 1 + %hi = load i64, ptr %7, align 8 + call void @test.test(ptr %lo, i64 %hi) + ret void +} + +define void @test.test(ptr %0, i64 %1) #0 { +entry: + %foo = alloca %"variant[]", align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %foo, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %foo, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + %4 = getelementptr inbounds %"variant[]", ptr %foo, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + %ptroffset = getelementptr inbounds %variant, ptr %5, i64 0 + %6 = getelementptr inbounds %variant, ptr %ptroffset, i32 0, i32 0 + %7 = load ptr, ptr %6, align 8 + %8 = load i32, ptr %7, align 8 + call void (ptr, ...) @printf(ptr @.str, i32 %8) + ret void +} + +define i32 @main() #0 { +entry: + %i = alloca i32, align 4 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [1 x %variant], align 16 + %taddr = alloca i32, align 4 + %vararg1 = alloca %"variant[]", align 8 + %varargslots2 = alloca [1 x %variant], align 16 + %taddr3 = alloca i32, align 4 + store i32 1, ptr %i, align 4 + store i32 1, ptr %taddr, align 4 + %0 = insertvalue %variant undef, ptr %taddr, 0 + %1 = insertvalue %variant %0, i64 ptrtoint (ptr @.typeid.int to i64), 1 + %2 = getelementptr inbounds [1 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %1, ptr %2, align 16 + %3 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 1, ptr %3, align 8 + %4 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo = load ptr, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi = load i64, ptr %6, align 8 + call void @test.test(ptr %lo, i64 %hi) + store i32 1, ptr %taddr3, align 4 + %7 = insertvalue %variant undef, ptr %taddr3, 0 + %8 = insertvalue %variant %7, i64 ptrtoint (ptr @.typeid.int to i64), 1 + %9 = getelementptr inbounds [1 x %variant], ptr %varargslots2, i64 0, i64 0 + store %variant %8, ptr %9, align 16 + %10 = getelementptr inbounds %"variant[]", ptr %vararg1, i32 0, i32 1 + store i64 1, ptr %10, align 8 + %11 = getelementptr inbounds %"variant[]", ptr %vararg1, i32 0, i32 0 + store ptr %varargslots2, ptr %11, align 8 + %12 = getelementptr inbounds { ptr, i64 }, ptr %vararg1, i32 0, i32 0 + %lo4 = load ptr, ptr %12, align 8 + %13 = getelementptr inbounds { ptr, i64 }, ptr %vararg1, i32 0, i32 1 + %hi5 = load i64, ptr %13, align 8 + call void @test.retest(ptr %lo4, i64 %hi5) + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite2/functions/vararg_argument_fails.c3 b/test/test_suite2/functions/vararg_argument_fails.c3 new file mode 100644 index 000000000..9e865b473 --- /dev/null +++ b/test/test_suite2/functions/vararg_argument_fails.c3 @@ -0,0 +1,5 @@ +fn void foo5(..., ...) {} // #error: Only a single vararg parameter is allowed + +fn void foo6(int ..., int ...) {} // #error: Only a single vararg parameter is allowed + +fn void foo7(int... x, int ... y) {} // #error: Only a single vararg parameter is allowed \ No newline at end of file diff --git a/test/test_suite2/functions/varargs.c3t b/test/test_suite2/functions/varargs.c3t new file mode 100644 index 000000000..0db8893de --- /dev/null +++ b/test/test_suite2/functions/varargs.c3t @@ -0,0 +1,42 @@ +module varargs; + +extern fn void printf(char* c, ...); + +fn void test() +{ + printf("%d\n", true); + printf("%d\n", 123); + printf("%f\n", 12.3); + ichar x1 = -123; + bool b = false; + float z1 = 12.3; + printf("%d\n", b); + printf("%d\n", x1); + printf("%f\n", z1); +} + +/* #expect: varargs.ll + +define void @varargs.test() #0 { +entry: + %x1 = alloca i8, align 1 + %b = alloca i8, align 1 + %z1 = alloca float, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 1) + call void (ptr, ...) @printf(ptr @.str.1, i32 123) + call void (ptr, ...) @printf(ptr @.str.2, double 1.230000e+01) + store i8 -123, ptr %x1, align 1 + store i8 0, ptr %b, align 1 + store float 0x40289999A0000000, ptr %z1, align 4 + %0 = load i8, ptr %b, align 1 + %1 = trunc i8 %0 to i1 + %boolsi = zext i1 %1 to i32 + call void (ptr, ...) @printf(ptr @.str.3, i32 %boolsi) + %2 = load i8, ptr %x1, align 1 + %sisiext = sext i8 %2 to i32 + call void (ptr, ...) @printf(ptr @.str.4, i32 %sisiext) + %3 = load float, ptr %z1, align 4 + %fpfpext = fpext float %3 to double + call void (ptr, ...) @printf(ptr @.str.5, double %fpfpext) + ret void +} diff --git a/test/test_suite2/generic/generic_copy.c3t b/test/test_suite2/generic/generic_copy.c3t new file mode 100644 index 000000000..ede601329 --- /dev/null +++ b/test/test_suite2/generic/generic_copy.c3t @@ -0,0 +1,12 @@ +module foo; + +fn void abc() +{ + int i; + defer { i++; } +} + +module tester; +import foo; + +define abc_my = foo::abc; \ No newline at end of file diff --git a/test/test_suite2/generic/generic_idents.c3t b/test/test_suite2/generic/generic_idents.c3t new file mode 100644 index 000000000..c957deedd --- /dev/null +++ b/test/test_suite2/generic/generic_idents.c3t @@ -0,0 +1,69 @@ +module gen ; + +fn Type mult(Type x) +{ + return x * x; +} + +fn Type addMult(Type x, Type a, Type b) +{ + return x * a + b; +} + +module test; +import gen; + +define intMult = gen::mult; +define doubleAddMult = gen::addMult; + +fn int getIt(int i) +{ + return intMult(i) + 1; +} + +fn double getIt2(double i) +{ + return doubleAddMult(i, 2, 3); +} + +// #expect: gen.int.ll + +define i32 @gen.int.mult(i32 %0) #0 { +entry: + %mul = mul i32 %0, %0 + ret i32 %mul +} + +define i32 @gen.int.addMult(i32 %0, i32 %1, i32 %2) #0 { +entry: + %mul = mul i32 %0, %1 + %add = add i32 %mul, %2 + ret i32 %add +} + + +// #expect: test.ll + +define i32 @test.getIt(i32 %0) #0 { +entry: + %1 = call i32 @gen.int.mult(i32 %0) + %add = add i32 %1, 1 + ret i32 %add +} + +define double @test.getIt2(double %0) #0 { +entry: + %1 = call double @gen.double.addMult(double %0, double 2.000000e+00, double 3.000000e+00) + ret double %1 +} + +declare i32 @gen.int.mult(i32) + +declare double @gen.double.addMult(double, double, double) + +// #expect: gen.double.ll + +define double @gen.double.addMult(double %0, double %1, double %2) + %fmul = fmul double %0, %1 + %fadd = fadd double %fmul, %2 + ret double %fadd diff --git a/test/test_suite2/globals/external_global.c3t b/test/test_suite2/globals/external_global.c3t new file mode 100644 index 000000000..358c132e1 --- /dev/null +++ b/test/test_suite2/globals/external_global.c3t @@ -0,0 +1,35 @@ +module test; + +struct MinInfo +{ + long offset; + uint file_attr; +} + +struct UzGlobs +{ + ichar answerbuf; + MinInfo[1] info; + MinInfo* pInfo; +} + +extern UzGlobs g; + +fn int extract_or_test_files() +{ + g.pInfo = &g.info; + return 0; +} + +/* #expect: test.ll + + +%UzGlobs = type { i8, [1 x %MinInfo], ptr } +%MinInfo = type { i64, i32 } + +@g = external global %UzGlobs, align 8 + +entry: + store ptr getelementptr inbounds (%UzGlobs, ptr @g, i32 0, i32 1), ptr getelementptr inbounds (%UzGlobs, ptr @g, i32 0, i32 2), align 8 + ret i32 0 +} diff --git a/test/test_suite2/globals/global_align.c3t b/test/test_suite2/globals/global_align.c3t new file mode 100644 index 000000000..67c16ba8f --- /dev/null +++ b/test/test_suite2/globals/global_align.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 + +module abc; + +int foo @align(32); + +fn void test() +{ + int x = foo; +} + +// #expect: abc.ll + +@abc.foo = local_unnamed_addr global i32 0, align 32 + +define void @abc.test() #0 { +entry: + %x = alloca i32, align 4 + %0 = load i32, ptr @abc.foo, align 32 + store i32 %0, ptr %x, align 4 + ret void +} diff --git a/test/test_suite2/globals/global_extname.c3t b/test/test_suite2/globals/global_extname.c3t new file mode 100644 index 000000000..6de9b442d --- /dev/null +++ b/test/test_suite2/globals/global_extname.c3t @@ -0,0 +1,7 @@ +module foo; + +int baz @extname("foobar") = 123; + +// #expect: foo.ll + +@foobar = local_unnamed_addr global i32 123, align 4 \ No newline at end of file diff --git a/test/test_suite2/globals/global_init.c3 b/test/test_suite2/globals/global_init.c3 new file mode 100644 index 000000000..b258a909f --- /dev/null +++ b/test/test_suite2/globals/global_init.c3 @@ -0,0 +1,23 @@ +// TODO string str = "hello"; +char* str2 = "hello"; +char[] str3 = "hello"; + + +int[2] a1 = { 1, 2 }; + +int[2] a2 = 30; // #error: 'int' into 'int[2]' +// TODO int[2] a3 = a1; + +ichar[*] a; // #error: Inferred array types can only be used in declarations with initializers + +ichar ca = 0; +ichar cb = 1; + +ichar cc = 127; +ichar cd = -128; + +ichar ce = 128; // #error: The value '128' is out of range for 'ichar' +ichar cf = -129; // #error: The value '-129' is out of range for 'ichar' + +ichar cg = 70000; // #error: The value '70000' is out of range for 'ichar' +ichar ch = -70000; // #error: The value '-70000' is out of range for 'ichar' \ No newline at end of file diff --git a/test/test_suite2/globals/misplaced_const.c3 b/test/test_suite2/globals/misplaced_const.c3 new file mode 100644 index 000000000..d8ebafd84 --- /dev/null +++ b/test/test_suite2/globals/misplaced_const.c3 @@ -0,0 +1,6 @@ +const FOO = 3; +int BAR = 4; // #error: This looks like a constant variable, did you forget 'const'? + +const BAZ = "ofke"; + +FOOBAR; // #error: Expected a top level declaration here. \ No newline at end of file diff --git a/test/test_suite2/globals/recursive_globals.c3 b/test/test_suite2/globals/recursive_globals.c3 new file mode 100644 index 000000000..d6d2a725f --- /dev/null +++ b/test/test_suite2/globals/recursive_globals.c3 @@ -0,0 +1,3 @@ +void *x = &x; + +int y = 1 + y; // #error: This looks like the initialization of the variable was circular. \ No newline at end of file diff --git a/test/test_suite2/globals/recursive_locals.c3 b/test/test_suite2/globals/recursive_locals.c3 new file mode 100644 index 000000000..1709dbf9f --- /dev/null +++ b/test/test_suite2/globals/recursive_locals.c3 @@ -0,0 +1,13 @@ + +struct List +{ + int x; + List* next; +} + +const List A = { 7, &B }; +const List B = { 8, &A }; + +extern List d; + +List c = { 7, &d }; diff --git a/test/test_suite2/globals/self_referencing_local.c3 b/test/test_suite2/globals/self_referencing_local.c3 new file mode 100644 index 000000000..6da61b7a8 --- /dev/null +++ b/test/test_suite2/globals/self_referencing_local.c3 @@ -0,0 +1,5 @@ +fn void test() +{ + void* x = &x; + int y = y; // #error: This looks like the initialization of the variable was circular. +} \ No newline at end of file diff --git a/test/test_suite2/globals/static_global.c3 b/test/test_suite2/globals/static_global.c3 new file mode 100644 index 000000000..227d5fd13 --- /dev/null +++ b/test/test_suite2/globals/static_global.c3 @@ -0,0 +1 @@ +static int ifej; // #error: Expected a top level declaration here \ No newline at end of file diff --git a/test/test_suite2/import/access_other_module.c3t b/test/test_suite2/import/access_other_module.c3t new file mode 100644 index 000000000..1c8d438ed --- /dev/null +++ b/test/test_suite2/import/access_other_module.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module foo; +import std::math; +fn void main() +{ + void* foekf = &math::log; + double* xok = &math::DIV_1_SQRT2; +} + +/* #expect: foo.ll + + +@"std::math.DIV_1_SQRT2" = external global double, align 8 + +define void @foo.main() #0 { +entry: + %foekf = alloca ptr, align 8 + %xok = alloca ptr, align 8 + store ptr @"std::math.log", ptr %foekf, align 8 + store ptr @"std::math.DIV_1_SQRT2", ptr %xok, align 8 + ret void +} + +declare double @"std::math.log"(double) \ No newline at end of file diff --git a/test/test_suite2/import/autoimport.c3 b/test/test_suite2/import/autoimport.c3 new file mode 100644 index 000000000..afdfc74de --- /dev/null +++ b/test/test_suite2/import/autoimport.c3 @@ -0,0 +1,36 @@ +module foo; + +fn int test() @autoimport +{ + return 1; +} + +macro int testm() @autoimport +{ + return 1; +} + +fn int test1() +{ + return 1; +} + +macro int testm1() +{ + return 1; +} + +module bar; +import foo; + +fn void main() +{ + testm(); + test(); +} + +fn void main2() +{ + testm1(); // #error: Macros from other modules must be prefixed with the module nam + test1(); // #error: Functions from other modules must be prefixed with the module nam +} \ No newline at end of file diff --git a/test/test_suite2/import/import_error.c3 b/test/test_suite2/import/import_error.c3 new file mode 100644 index 000000000..4be9e0f7c --- /dev/null +++ b/test/test_suite2/import/import_error.c3 @@ -0,0 +1,6 @@ +module test; +import std::core::mem; +import hello_world; // #error: No module named +import test; // #error: Importing the current + +fn void hello() { } \ No newline at end of file diff --git a/test/test_suite2/import/import_error_multi.c3 b/test/test_suite2/import/import_error_multi.c3 new file mode 100644 index 000000000..e6a761a42 --- /dev/null +++ b/test/test_suite2/import/import_error_multi.c3 @@ -0,0 +1 @@ +import foo, ; // #error: Another module name was expected after \ No newline at end of file diff --git a/test/test_suite2/import/import_error_out_of_order.c3 b/test/test_suite2/import/import_error_out_of_order.c3 new file mode 100644 index 000000000..63e28ae0c --- /dev/null +++ b/test/test_suite2/import/import_error_out_of_order.c3 @@ -0,0 +1,5 @@ +module foo; + +fn void hello() {} + +import bar; // #error: Imports are only allowed directly after the module declaration \ No newline at end of file diff --git a/test/test_suite2/import/import_error_string.c3 b/test/test_suite2/import/import_error_string.c3 new file mode 100644 index 000000000..1810dcfe3 --- /dev/null +++ b/test/test_suite2/import/import_error_string.c3 @@ -0,0 +1 @@ +import "Hello my friend"; // #error: An import should be followed by a plain identifier, not a string. Did you accidentally put the module name between ""? \ No newline at end of file diff --git a/test/test_suite2/import/import_implicit.c3 b/test/test_suite2/import/import_implicit.c3 new file mode 100644 index 000000000..e88d58023 --- /dev/null +++ b/test/test_suite2/import/import_implicit.c3 @@ -0,0 +1,17 @@ +module abc; + +struct Foo +{ + int a; + int b; +} + +fn void test() {} + +module dde; + +fn void test() +{ + abc::test(); // #error: Did you mean the function 'abc::test' + Foo f; // #error: Did you mean the struct 'Foo' +} \ No newline at end of file diff --git a/test/test_suite2/import/import_works.c3t b/test/test_suite2/import/import_works.c3t new file mode 100644 index 000000000..c524cd8cf --- /dev/null +++ b/test/test_suite2/import/import_works.c3t @@ -0,0 +1,3 @@ +import std::io, std::core::mem; + +int foo = 1; \ No newline at end of file diff --git a/test/test_suite2/initializer_lists/disallowed_lists.c3 b/test/test_suite2/initializer_lists/disallowed_lists.c3 new file mode 100644 index 000000000..abfcb2617 --- /dev/null +++ b/test/test_suite2/initializer_lists/disallowed_lists.c3 @@ -0,0 +1,8 @@ +fn void test() +{ + char* hello = "123"; + char[] a = { '1', '2', '3' }; + char[*] b = { '1', '2', '3' }; + char[3] c = { '1', '2', '3' }; + char* d = { '1', '2', '3' }; // #error: Pointers cannot be initialized using an initializer list, instead you need to take the address of an array +} \ No newline at end of file diff --git a/test/test_suite2/initializer_lists/fasta.c3t b/test/test_suite2/initializer_lists/fasta.c3t new file mode 100644 index 000000000..aa1e53359 --- /dev/null +++ b/test/test_suite2/initializer_lists/fasta.c3t @@ -0,0 +1,373 @@ +// #target: macos-x64 +module fasta; + +const IM = 139968u; +const IA = 3877u; +const IC = 29573u; +const SEED = 42u; + +uint seed = SEED; + +fn float fasta_rand(float maxval) +{ + seed = (seed * IA + IC) % IM; + return maxval * seed / IM; +} + +private char[] alu = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +extern fn int atoi(char *s); +extern fn int printf(char *s, ...); +extern fn void putchar(int c); + +char[] iub = "acgtBDHKMNRSVWY"; +double[] iub_p = { + 0.27, + 0.12, + 0.12, + 0.27, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02 }; + +char[] homosapiens = "acgt"; +double[] homosapiens_p = { + 0.3029549426680, + 0.1979883004921, + 0.1975473066391, + 0.3015094502008 +}; + +const LINELEN = 60; + +// slowest character-at-a-time output +fn void repeat_fasta(char[] seq, int n) +{ + usize len = seq.len; + int i = void; + for (i = 0; i < n; i++) + { + putchar(seq[i % len]); + if (i % LINELEN == LINELEN - 1) putchar('\n'); + } + if (i % LINELEN != 0) putchar('\n'); +} + +fn void random_fasta(char[] symb, double[] probability, int n) +{ + assert(symb.len == probability.len); + int len = probability.len; + int i = void; + for (i = 0; i < n; i++) + { + double v = fasta_rand(1.0); + /* slowest idiomatic linear lookup. Fast if len is short though. */ + int j = void; + for (j = 0; j < len - 1; j++) + { + v -= probability[j]; + if (v < 0) break; + } + putchar(symb[j]); + if (i % LINELEN == LINELEN - 1) putchar('\n'); + } + if (i % LINELEN != 0) putchar('\n'); +} + +fn void main(int argc, char **argv) +{ + int n = 1000; + if (argc > 1) n = atoi(argv[1]); + + printf(">ONE Homo sapiens alu\n"); + repeat_fasta(alu, n * 2); + + printf(">TWO IUB ambiguity codes\n"); + random_fasta(iub, iub_p, n * 3); + + printf(">THREE Homo sapiens frequency\n"); + random_fasta(homosapiens, homosapiens_p, n * 5); + +} + +/* #expect: fasta.ll + +%"char[]" = type { ptr, i64 } +%"double[]" = type { ptr, i64 } + +@fasta.IM = local_unnamed_addr constant i32 139968, align 4 +@fasta.IA = local_unnamed_addr constant i32 3877, align 4 +@fasta.IC = local_unnamed_addr constant i32 29573, align 4 +@fasta.SEED = local_unnamed_addr constant i32 42, align 4 +@fasta.seed = local_unnamed_addr global i32 42, align 4 +@.str = private unnamed_addr constant [288 x i8] c"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA\00", align 1 +@fasta.alu = protected unnamed_addr global %"char[]" { ptr @.str, i64 287 }, align 8 +@.str.11 = private unnamed_addr constant [16 x i8] c"acgtBDHKMNRSVWY\00", align 1 +@fasta.iub = local_unnamed_addr global %"char[]" { ptr @.str.11, i64 15 }, align 8 +@.taddr = private global [15 x double] [double 2.700000e-01, double 1.200000e-01, double 1.200000e-01, double 2.700000e-01, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02], align 8 +@fasta.iub_p = local_unnamed_addr global %"double[]" { ptr @.taddr, i64 15 }, align 8 +@.str.12 = private unnamed_addr constant [5 x i8] c"acgt\00", align 1 +@fasta.homosapiens = local_unnamed_addr global %"char[]" { ptr @.str.12, i64 4 }, align 8 +@.taddr.13 = private global [4 x double] [double 0x3FD3639D20BAEB5B, double 0x3FC957AE3DCD561B, double 0x3FC9493AEAB6C2BF, double 0x3FD34BEE4B030838], align 8 +@fasta.homosapiens_p = local_unnamed_addr global %"double[]" { ptr @.taddr.13, i64 4 }, align 8 +@fasta.LINELEN = local_unnamed_addr constant i32 60, align 4 +@.str.14 = private unnamed_addr constant [23 x i8] c">ONE Homo sapiens alu\0A\00", align 1 +@.str.15 = private unnamed_addr constant [26 x i8] c">TWO IUB ambiguity codes\0A\00", align 1 +@.str.16 = private unnamed_addr constant [31 x i8] c">THREE Homo sapiens frequency\0A\00", align 1 + +; Function Attrs: nounwind +define float @fasta.fasta_rand(float %0) #0 { +entry: + %1 = load i32, ptr @fasta.seed, align 4 + %mul = mul i32 %1, 3877 + %add = add i32 %mul, 29573 + %umod = urem i32 %add, 139968 + store i32 %umod, ptr @fasta.seed, align 4 + %2 = load i32, ptr @fasta.seed, align 4 + %uifp = uitofp i32 %2 to float + %fmul = fmul float %0, %uifp + %fdiv = fdiv float %fmul, 1.399680e+05 + ret float %fdiv +} + +; Function Attrs: nounwind +declare i32 @atoi(ptr) #0 + +; Function Attrs: nounwind +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: nounwind +declare void @putchar(i32) #0 + +; Function Attrs: nounwind +define void @fasta.repeat_fasta(ptr %0, i64 %1, i32 %2) #0 { +entry: + %seq = alloca %"char[]", align 8 + %len = alloca i64, align 8 + %i = alloca i32, align 4 + %3 = getelementptr inbounds { ptr, i64 }, ptr %seq, i32 0, i32 0 + store ptr %0, ptr %3, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %seq, i32 0, i32 1 + store i64 %1, ptr %4, align 8 + %5 = getelementptr inbounds %"char[]", ptr %seq, i32 0, i32 1 + %6 = load i64, ptr %5, align 8 + store i64 %6, ptr %len, align 8 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %if.exit, %entry + %7 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %7, %2 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %8 = getelementptr inbounds %"char[]", ptr %seq, i32 0, i32 0 + %9 = load ptr, ptr %8, align 8 + %10 = load i32, ptr %i, align 4 + %sisiext = sext i32 %10 to i64 + %11 = load i64, ptr %len, align 8 + %smod = srem i64 %sisiext, %11 + %ptroffset = getelementptr inbounds i8, ptr %9, i64 %smod + %12 = load i8, ptr %ptroffset, align 1 + %uisiext = zext i8 %12 to i32 + call void @putchar(i32 %uisiext) + %13 = load i32, ptr %i, align 4 + %smod1 = srem i32 %13, 60 + %eq = icmp eq i32 %smod1, 59 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + call void @putchar(i32 10) + br label %if.exit + +if.exit: ; preds = %if.then, %loop.body + %14 = load i32, ptr %i, align 4 + %add = add i32 %14, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %15 = load i32, ptr %i, align 4 + %smod2 = srem i32 %15, 60 + %neq = icmp ne i32 %smod2, 0 + br i1 %neq, label %if.then3, label %if.exit4 + +if.then3: ; preds = %loop.exit + call void @putchar(i32 10) + br label %if.exit4 + +if.exit4: ; preds = %if.then3, %loop.exit + ret void +} + +; Function Attrs: nounwind +define void @fasta.random_fasta(ptr %0, i64 %1, ptr %2, i64 %3, i32 %4) #0 { +entry: + %symb = alloca %"char[]", align 8 + %probability = alloca %"double[]", align 8 + %len = alloca i32, align 4 + %i = alloca i32, align 4 + %v = alloca double, align 8 + %j = alloca i32, align 4 + %5 = getelementptr inbounds { ptr, i64 }, ptr %symb, i32 0, i32 0 + store ptr %0, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %symb, i32 0, i32 1 + store i64 %1, ptr %6, align 8 + %7 = getelementptr inbounds { ptr, i64 }, ptr %probability, i32 0, i32 0 + store ptr %2, ptr %7, align 8 + %8 = getelementptr inbounds { ptr, i64 }, ptr %probability, i32 0, i32 1 + store i64 %3, ptr %8, align 8 + %9 = getelementptr inbounds %"char[]", ptr %symb, i32 0, i32 1 + %10 = load i64, ptr %9, align 8 + %11 = getelementptr inbounds %"double[]", ptr %probability, i32 0, i32 1 + %12 = load i64, ptr %11, align 8 + %eq = icmp eq i64 %10, %12 + call void @llvm.assume(i1 %eq) + %13 = getelementptr inbounds %"double[]", ptr %probability, i32 0, i32 1 + %14 = load i64, ptr %13, align 8 + %uisitrunc = trunc i64 %14 to i32 + store i32 %uisitrunc, ptr %len, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %if.exit9, %entry + %15 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %15, %4 + br i1 %lt, label %loop.body, label %loop.exit11 + +loop.body: ; preds = %loop.cond + %16 = call float @fasta.fasta_rand(float 1.000000e+00) + %fpfpext = fpext float %16 to double + store double %fpfpext, ptr %v, align 8 + store i32 0, ptr %j, align 4 + br label %loop.cond1 + +loop.cond1: ; preds = %if.exit, %loop.body + %17 = load i32, ptr %j, align 4 + %18 = load i32, ptr %len, align 4 + %sub = sub i32 %18, 1 + %lt2 = icmp slt i32 %17, %sub + br i1 %lt2, label %loop.body3, label %loop.exit + +loop.body3: ; preds = %loop.cond1 + %19 = load double, ptr %v, align 8 + %20 = getelementptr inbounds %"double[]", ptr %probability, i32 0, i32 0 + %21 = load ptr, ptr %20, align 8 + %22 = load i32, ptr %j, align 4 + %sisiext = sext i32 %22 to i64 + %ptroffset = getelementptr inbounds double, ptr %21, i64 %sisiext + %23 = load double, ptr %ptroffset, align 8 + %fsub = fsub double %19, %23 + store double %fsub, ptr %v, align 8 + %24 = load double, ptr %v, align 8 + %lt4 = fcmp olt double %24, 0.000000e+00 + br i1 %lt4, label %if.then, label %if.exit + +if.then: ; preds = %loop.body3 + br label %loop.exit + +if.exit: ; preds = %loop.body3 + %25 = load i32, ptr %j, align 4 + %add = add i32 %25, 1 + store i32 %add, ptr %j, align 4 + br label %loop.cond1 + +loop.exit: ; preds = %if.then, %loop.cond1 + %26 = getelementptr inbounds %"char[]", ptr %symb, i32 0, i32 0 + %27 = load ptr, ptr %26, align 8 + %28 = load i32, ptr %j, align 4 + %sisiext5 = sext i32 %28 to i64 + %ptroffset6 = getelementptr inbounds i8, ptr %27, i64 %sisiext5 + %29 = load i8, ptr %ptroffset6, align 1 + %uisiext = zext i8 %29 to i32 + call void @putchar(i32 %uisiext) + %30 = load i32, ptr %i, align 4 + %smod = srem i32 %30, 60 + %eq7 = icmp eq i32 %smod, 59 + br i1 %eq7, label %if.then8, label %if.exit9 + +if.then8: ; preds = %loop.exit + call void @putchar(i32 10) + br label %if.exit9 + +if.exit9: ; preds = %if.then8, %loop.exit + %31 = load i32, ptr %i, align 4 + %add10 = add i32 %31, 1 + store i32 %add10, ptr %i, align 4 + br label %loop.cond + +loop.exit11: ; preds = %loop.cond + %32 = load i32, ptr %i, align 4 + %smod12 = srem i32 %32, 60 + %neq = icmp ne i32 %smod12, 0 + br i1 %neq, label %if.then13, label %if.exit14 + +if.then13: ; preds = %loop.exit11 + call void @putchar(i32 10) + br label %if.exit14 + +if.exit14: ; preds = %if.then13, %loop.exit11 + ret void +} + +; Function Attrs: nounwind +define void @fasta.main(i32 %0, ptr %1) #0 { +entry: + %n = alloca i32, align 4 + store i32 1000, ptr %n, align 4 + %gt = icmp sgt i32 %0, 1 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %ptroffset = getelementptr inbounds ptr, ptr %1, i64 1 + %2 = load ptr, ptr %ptroffset, align 8 + %3 = call i32 @atoi(ptr %2) + store i32 %3, ptr %n, align 4 + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %4 = call i32 (ptr, ...) @printf(ptr @.str.14) + %lo = load ptr, ptr @fasta.alu, align 8 + %hi = load i64, ptr getelementptr inbounds ({ ptr, i64 }, ptr @fasta.alu, i32 0, i32 1), align 8 + %5 = load i32, ptr %n, align 4 + %mul = mul i32 %5, 2 + call void @fasta.repeat_fasta(ptr %lo, i64 %hi, i32 %mul) + %6 = call i32 (ptr, ...) @printf(ptr @.str.15) + %lo1 = load ptr, ptr @fasta.iub, align 8 + %hi2 = load i64, ptr getelementptr inbounds ({ ptr, i64 }, ptr @fasta.iub, i32 0, i32 1), align 8 + %lo3 = load ptr, ptr @fasta.iub_p, align 8 + %hi4 = load i64, ptr getelementptr inbounds ({ ptr, i64 }, ptr @fasta.iub_p, i32 0, i32 1), align 8 + %7 = load i32, ptr %n, align 4 + %mul5 = mul i32 %7, 3 + call void @fasta.random_fasta(ptr %lo1, i64 %hi2, ptr %lo3, i64 %hi4, i32 %mul5) + %8 = call i32 (ptr, ...) @printf(ptr @.str.16) + %lo6 = load ptr, ptr @fasta.homosapiens, align 8 + %hi7 = load i64, ptr getelementptr inbounds ({ ptr, i64 }, ptr @fasta.homosapiens, i32 0, i32 1), align 8 + %lo8 = load ptr, ptr @fasta.homosapiens_p, align 8 + %hi9 = load i64, ptr getelementptr inbounds ({ ptr, i64 }, ptr @fasta.homosapiens_p, i32 0, i32 1), align 8 + %9 = load i32, ptr %n, align 4 + %mul10 = mul i32 %9, 5 + call void @fasta.random_fasta(ptr %lo6, i64 %hi7, ptr %lo8, i64 %hi9, i32 %mul10) + ret void +} + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @fasta.main(i32 %0, ptr %1) + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite2/initializer_lists/general_tests.c3t b/test/test_suite2/initializer_lists/general_tests.c3t new file mode 100644 index 000000000..71ecfa811 --- /dev/null +++ b/test/test_suite2/initializer_lists/general_tests.c3t @@ -0,0 +1,96 @@ +// #target: macos-x64 + +union Baz +{ + int x; + double y; +} +struct Bar +{ + int x; + int y; +} + +fn int test() +{ + Baz ffe = { .x = 1 }; + int[1] azz = {}; + int[*] a = {}; + var $foo = { 11, 22, 33 }; + static int foo1 = $foo[1]; + int foo2 = $foo[2]; + var $foos = { "Hello!" }; + char* str = $foos[0]; + bool x = ! int[] { 1, 2, 3 }; + Bar b = {}; + Baz z = {}; + int[] sub = {}; + Bar[] foo = {}; + Baz[3] baz = {}; + return 1; +} + + +/* #expect: general_tests.ll + +%Baz = type { double } +%Bar = type { i32, i32 } +%"int[]" = type { ptr, i64 } +%"Bar[]" = type { ptr, i64 } + +@.typeid.general_tests.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.general_tests.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.__const = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8 +@test.foo1 = internal unnamed_addr global i32 22, align 4 +@.str = private unnamed_addr constant [7 x i8] c"Hello!\00", align 1 + +; Function Attrs: nounwind +define i32 @general_tests.test() #0 { +entry: + %ffe = alloca %Baz, align 8 + %azz = alloca [1 x i32], align 4 + %a = alloca [0 x i32], align 4 + %foo2 = alloca i32, align 4 + %str = alloca ptr, align 8 + %x = alloca i8, align 1 + %literal = alloca [3 x i32], align 4 + %b = alloca %Bar, align 4 + %z = alloca %Baz, align 8 + %sub = alloca %"int[]", align 8 + %literal1 = alloca [0 x i32], align 4 + %foo = alloca %"Bar[]", align 8 + %literal2 = alloca [0 x %Bar], align 4 + %baz = alloca [3 x %Baz], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ffe, ptr align 8 @.__const, i32 8, i1 false) + %0 = getelementptr inbounds [1 x i32], ptr %azz, i64 0, i64 0 + store i32 0, ptr %0, align 4 + store i32 33, ptr %foo2, align 4 + store ptr @.str, ptr %str, align 8 + %1 = getelementptr inbounds [3 x i32], ptr %literal, i64 0, i64 0 + store i32 1, ptr %1, align 4 + %2 = getelementptr inbounds [3 x i32], ptr %literal, i64 0, i64 1 + store i32 2, ptr %2, align 4 + %3 = getelementptr inbounds [3 x i32], ptr %literal, i64 0, i64 2 + store i32 3, ptr %3, align 4 + %4 = insertvalue %"int[]" undef, ptr %literal, 0 + %5 = insertvalue %"int[]" %4, i64 3, 1 + %len = extractvalue %"int[]" %5, 1 + %not = icmp eq i64 %len, 0 + %6 = zext i1 %not to i8 + store i8 %6, ptr %x, align 1 + %7 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 0 + store i32 0, ptr %7, align 4 + %8 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 1 + store i32 0, ptr %8, align 4 + call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) + store [0 x i32] zeroinitializer, ptr %literal1, align 4 + %9 = insertvalue %"int[]" undef, ptr %literal1, 0 + %10 = insertvalue %"int[]" %9, i64 0, 1 + store %"int[]" %10, ptr %sub, align 8 + store [0 x %Bar] zeroinitializer, ptr %literal2, align 4 + %11 = insertvalue %"Bar[]" undef, ptr %literal2, 0 + %12 = insertvalue %"Bar[]" %11, i64 0, 1 + store %"Bar[]" %12, ptr %foo, align 8 + call void @llvm.memset.p0.i64(ptr align 16 %baz, i8 0, i64 24, i1 false) + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite2/initializer_lists/indexing_into_complist.c3 b/test/test_suite2/initializer_lists/indexing_into_complist.c3 new file mode 100644 index 000000000..27b96140b --- /dev/null +++ b/test/test_suite2/initializer_lists/indexing_into_complist.c3 @@ -0,0 +1,28 @@ +fn void test() +{ + char* c = { 1, 3, "hello"}[2]; + int x; + int z = { 1, 3 }[x]; // #error: To subscript a compile time list a compile time integer index is needed +} + +fn void test2() +{ + int z = { 1, 3 }[-1]; // #error: The index may not be negative +} + +fn void test3() +{ + int z = { 1, 3 }[0xFFFF_FFFF_FFFF_FFFFu64]; // #error: The index is out of range. +} + +fn void test4() +{ + int z = { 1, 3 }[2]; // #error: An index of '2' is out of range, a value between 0 and 1 was expected. + int z2 = { 1 }[2]; // #error: An index of '2' is out of range, a value of 0 was expected. +} + +fn void test5() +{ + int z = { 1, 3 }[^4]; // #error: An index of '4' from the end is out of range, a value between 1 and 2 was expected + int z2 = { 1 }[^4]; // #error: An index of '4' from the end is out of range, a value of 1 was expected. +} diff --git a/test/test_suite2/initializer_lists/ranges_to_dynamic.c3t b/test/test_suite2/initializer_lists/ranges_to_dynamic.c3t new file mode 100644 index 000000000..f15881256 --- /dev/null +++ b/test/test_suite2/initializer_lists/ranges_to_dynamic.c3t @@ -0,0 +1,64 @@ +// #target: mingw-x64 +module test; + +extern fn void printf(char*, ...); + +fn void test(int x) +{ + int[10] y = { [0..3] = 4, [6..8] = x }; + foreach (int v : y) + { + printf("%d\n", v); + } +} + +fn void main() +{ + test(101); +} + +/* #expect: test.ll + +define void @test.test(i32 %0) #0 { +entry: + %y = alloca [10 x i32], align 16 + %anon = alloca i64, align 8 + %v = alloca i32, align 4 + call void @llvm.memset.p0.i64(ptr align 16 %y, i8 0, i64 40, i1 false) + %1 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 0 + store i32 4, ptr %1, align 4 + %2 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 1 + store i32 4, ptr %2, align 4 + %3 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 2 + store i32 4, ptr %3, align 4 + %4 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 3 + store i32 4, ptr %4, align 4 + %5 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 6 + store i32 %0, ptr %5, align 4 + %6 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 7 + store i32 %0, ptr %6, align 4 + %7 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 8 + store i32 %0, ptr %7, align 4 + store i64 0, ptr %anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %8 = load i64, ptr %anon, align 8 + %gt = icmp ugt i64 10, %8 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %9 = load i64, ptr %anon, align 8 + %10 = getelementptr inbounds [10 x i32], ptr %y, i64 0, i64 %9 + %11 = load i32, ptr %10, align 4 + store i32 %11, ptr %v, align 4 + %12 = load i32, ptr %v, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %12) + %13 = load i64, ptr %anon, align 8 + %add = add i64 %13, 1 + store i64 %add, ptr %anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} \ No newline at end of file diff --git a/test/test_suite2/initializer_lists/statics.c3t b/test/test_suite2/initializer_lists/statics.c3t new file mode 100644 index 000000000..169e1774b --- /dev/null +++ b/test/test_suite2/initializer_lists/statics.c3t @@ -0,0 +1,90 @@ +// #target: macos-x64 +import std::io; +import libc; +union Baz +{ + int x; + double y; +} +struct Bar +{ + int x; + int y; +} + + +fn void test() +{ + Bar[] b = { { 1, 2 } }; + static Bar[] c = { { 1, 2 } }; + libc::printf("%d %d\n", b[0].y, c[0].y); + b[0].y += 1; + c[0].y += 1; + +} +fn int main() +{ + test(); + test(); + test(); + return 1; +} + +/* #expect: statics.ll + +%Bar = type { i32, i32 } +%"Bar[]" = type { ptr, i64 } + +@.typeid.statics.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.statics.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.taddr = private global [1 x %Bar] [%Bar { i32 1, i32 2 }], align 8 +@test.c = internal unnamed_addr global %"Bar[]" { ptr @.taddr, i64 1 }, align 8 +@.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 + +define void @statics.test() #0 { +entry: + %b = alloca %"Bar[]", align 8 + %literal = alloca [1 x %Bar], align 4 + %0 = getelementptr inbounds [1 x %Bar], ptr %literal, i64 0, i64 0 + %1 = getelementptr inbounds %Bar, ptr %0, i32 0, i32 0 + store i32 1, ptr %1, align 4 + %2 = getelementptr inbounds %Bar, ptr %0, i32 0, i32 1 + store i32 2, ptr %2, align 4 + %3 = insertvalue %"Bar[]" undef, ptr %literal, 0 + %4 = insertvalue %"Bar[]" %3, i64 1, 1 + store %"Bar[]" %4, ptr %b, align 8 + %5 = getelementptr inbounds %"Bar[]", ptr %b, i32 0, i32 0 + %6 = load ptr, ptr %5, align 8 + %ptroffset = getelementptr inbounds %Bar, ptr %6, i64 0 + %7 = getelementptr inbounds %Bar, ptr %ptroffset, i32 0, i32 1 + %8 = load i32, ptr %7, align 4 + %9 = load ptr, ptr @test.c, align 8 + %ptroffset1 = getelementptr inbounds %Bar, ptr %9, i64 0 + %10 = getelementptr inbounds %Bar, ptr %ptroffset1, i32 0, i32 1 + %11 = load i32, ptr %10, align 4 + %12 = call i32 (ptr, ...) @printf(ptr @.str, i32 %8, i32 %11) + %13 = getelementptr inbounds %"Bar[]", ptr %b, i32 0, i32 0 + %14 = load ptr, ptr %13, align 8 + %ptroffset2 = getelementptr inbounds %Bar, ptr %14, i64 0 + %15 = getelementptr inbounds %Bar, ptr %ptroffset2, i32 0, i32 1 + %16 = load i32, ptr %15, align 4 + %add = add i32 %16, 1 + store i32 %add, ptr %15, align 4 + %17 = load ptr, ptr @test.c, align 8 + %ptroffset3 = getelementptr inbounds %Bar, ptr %17, i64 0 + %18 = getelementptr inbounds %Bar, ptr %ptroffset3, i32 0, i32 1 + %19 = load i32, ptr %18, align 4 + %add4 = add i32 %19, 1 + store i32 %add4, ptr %18, align 4 + ret void +} + +define i32 @main() #0 { +entry: + call void @statics.test() + call void @statics.test() + call void @statics.test() + ret i32 1 +} + +declare i32 @printf(ptr, ...) \ No newline at end of file diff --git a/test/test_suite2/initializer_lists/subarrays.c3t b/test/test_suite2/initializer_lists/subarrays.c3t new file mode 100644 index 000000000..cd6c93a77 --- /dev/null +++ b/test/test_suite2/initializer_lists/subarrays.c3t @@ -0,0 +1,170 @@ +// #target: macos-x64 + +import std::io; +import std::core::mem; +import libc; +union Baz +{ + int x; + double y; +} +struct Bar +{ + int x; + int y; +} + + +Bar[] arrbar = { { 3, 4 }, { 8, 9 }}; +int[] xd = { 1, 2 }; +int* fofeo = &&(int[2]{ 3, 4 }); + +fn int main() +{ + Bar w = arrbar[1]; + libc::printf("%d\n", arrbar[1].x); + int[] x = { 1, 2, 3 }; + int* y = &&(int[3]{ 123, 234, 567 }); + io::println("Start:"); + libc::printf("X len: %d mid element %d\n", (int)(x.len), x[1]); + libc::printf("Y mid element %d\n", y[1]); + libc::printf("Fofeo second element %d\n", fofeo[1]); + Baz ffe = { .x = 1 }; + int[1] azz = {}; + int[*] a = {}; + + //var $foo = { 1, 2, 3 }; + bool xy = ! int[] { 1, 2, 3 }; + if (!xy) io::println("Ok"); + Bar b = {}; + Baz z = {}; + int[] sub = {}; + Bar[] foo = {}; + Baz[3] baz = {}; + return 1; +} + +/* #expect: subarrays.ll + +%Bar = type { i32, i32 } +%"Bar[]" = type { ptr, i64 } +%"int[]" = type { ptr, i64 } +%Baz = type { double } + +@.typeid.subarrays.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8 +@.typeid.subarrays.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.taddr = private global [2 x %Bar] [%Bar { i32 3, i32 4 }, %Bar { i32 8, i32 9 }], align 8 +@subarrays.arrbar = local_unnamed_addr global %"Bar[]" { ptr @.taddr, i64 2 }, align 8 +@.taddr.3 = private global [2 x i32] [i32 1, i32 2], align 4 +@subarrays.xd = local_unnamed_addr global %"int[]" { ptr @.taddr.3, i64 2 }, align 8 +@.taddr.4 = private global [2 x i32] [i32 3, i32 4], align 4 +@subarrays.fofeo = local_unnamed_addr global ptr @.taddr.4, align 8 +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@.str.5 = private unnamed_addr constant [7 x i8] c"Start:\00", align 1 +@.str.6 = private unnamed_addr constant [26 x i8] c"X len: %d mid element %d\0A\00", align 1 +@.str.7 = private unnamed_addr constant [18 x i8] c"Y mid element %d\0A\00", align 1 +@.str.8 = private unnamed_addr constant [25 x i8] c"Fofeo second element %d\0A\00", align 1 +@.__const = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8 +@.str.9 = private unnamed_addr constant [3 x i8] c"Ok\00", align 1 + +define i32 @main() #0 { +entry: + %w = alloca %Bar, align 4 + %x = alloca %"int[]", align 8 + %literal = alloca [3 x i32], align 4 + %y = alloca ptr, align 8 + %literal2 = alloca [3 x i32], align 4 + %ffe = alloca %Baz, align 8 + %azz = alloca [1 x i32], align 4 + %a = alloca [0 x i32], align 4 + %xy = alloca i8, align 1 + %literal6 = alloca [3 x i32], align 4 + %b = alloca %Bar, align 4 + %z = alloca %Baz, align 8 + %sub = alloca %"int[]", align 8 + %literal8 = alloca [0 x i32], align 4 + %foo = alloca %"Bar[]", align 8 + %literal9 = alloca [0 x %Bar], align 4 + %baz = alloca [3 x %Baz], align 16 + %0 = load ptr, ptr @subarrays.arrbar, align 8 + %ptroffset = getelementptr inbounds %Bar, ptr %0, i64 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %w, ptr align 4 %ptroffset, i32 8, i1 false) + %1 = load ptr, ptr @subarrays.arrbar, align 8 + %ptroffset1 = getelementptr inbounds %Bar, ptr %1, i64 1 + %2 = getelementptr inbounds %Bar, ptr %ptroffset1, i32 0, i32 0 + %3 = load i32, ptr %2, align 4 + %4 = call i32 (ptr, ...) @printf(ptr @.str, i32 %3) + %5 = getelementptr inbounds [3 x i32], ptr %literal, i64 0, i64 0 + store i32 1, ptr %5, align 4 + %6 = getelementptr inbounds [3 x i32], ptr %literal, i64 0, i64 1 + store i32 2, ptr %6, align 4 + %7 = getelementptr inbounds [3 x i32], ptr %literal, i64 0, i64 2 + store i32 3, ptr %7, align 4 + %8 = insertvalue %"int[]" undef, ptr %literal, 0 + %9 = insertvalue %"int[]" %8, i64 3, 1 + store %"int[]" %9, ptr %x, align 8 + %10 = getelementptr inbounds [3 x i32], ptr %literal2, i64 0, i64 0 + store i32 123, ptr %10, align 4 + %11 = getelementptr inbounds [3 x i32], ptr %literal2, i64 0, i64 1 + store i32 234, ptr %11, align 4 + %12 = getelementptr inbounds [3 x i32], ptr %literal2, i64 0, i64 2 + store i32 567, ptr %12, align 4 + store ptr %literal2, ptr %y, align 8 + %13 = call i32 @"std::io.println"(ptr @.str.5) #3 + %14 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 1 + %15 = load i64, ptr %14, align 8 + %uisitrunc = trunc i64 %15 to i32 + %16 = getelementptr inbounds %"int[]", ptr %x, i32 0, i32 0 + %17 = load ptr, ptr %16, align 8 + %ptroffset3 = getelementptr inbounds i32, ptr %17, i64 1 + %18 = load i32, ptr %ptroffset3, align 4 + %19 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %uisitrunc, i32 %18) + %20 = load ptr, ptr %y, align 8 + %ptroffset4 = getelementptr inbounds i32, ptr %20, i64 1 + %21 = load i32, ptr %ptroffset4, align 4 + %22 = call i32 (ptr, ...) @printf(ptr @.str.7, i32 %21) + %23 = load ptr, ptr @subarrays.fofeo, align 8 + %ptroffset5 = getelementptr inbounds i32, ptr %23, i64 1 + %24 = load i32, ptr %ptroffset5, align 4 + %25 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %24) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ffe, ptr align 8 @.__const, i32 8, i1 false) + %26 = getelementptr inbounds [1 x i32], ptr %azz, i64 0, i64 0 + store i32 0, ptr %26, align 4 + %27 = getelementptr inbounds [3 x i32], ptr %literal6, i64 0, i64 0 + store i32 1, ptr %27, align 4 + %28 = getelementptr inbounds [3 x i32], ptr %literal6, i64 0, i64 1 + store i32 2, ptr %28, align 4 + %29 = getelementptr inbounds [3 x i32], ptr %literal6, i64 0, i64 2 + store i32 3, ptr %29, align 4 + %30 = insertvalue %"int[]" undef, ptr %literal6, 0 + %31 = insertvalue %"int[]" %30, i64 3, 1 + %len = extractvalue %"int[]" %31, 1 + %not = icmp eq i64 %len, 0 + %32 = zext i1 %not to i8 + store i8 %32, ptr %xy, align 1 + %33 = load i8, ptr %xy, align 1 + %34 = trunc i8 %33 to i1 + %not7 = xor i1 %34, true + br i1 %not7, label %if.then, label %if.exit + +if.then: ; preds = %entry + %35 = call i32 @"std::io.println"(ptr @.str.9) #3 + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %36 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 0 + store i32 0, ptr %36, align 4 + %37 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 1 + store i32 0, ptr %37, align 4 + call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) + store [0 x i32] zeroinitializer, ptr %literal8, align 4 + %38 = insertvalue %"int[]" undef, ptr %literal8, 0 + %39 = insertvalue %"int[]" %38, i64 0, 1 + store %"int[]" %39, ptr %sub, align 8 + store [0 x %Bar] zeroinitializer, ptr %literal9, align 4 + %40 = insertvalue %"Bar[]" undef, ptr %literal9, 0 + %41 = insertvalue %"Bar[]" %40, i64 0, 1 + store %"Bar[]" %41, ptr %foo, align 8 + call void @llvm.memset.p0.i64(ptr align 16 %baz, i8 0, i64 24, i1 false) + ret i32 1 +} diff --git a/test/test_suite2/initializer_lists/zero_init.c3t b/test/test_suite2/initializer_lists/zero_init.c3t new file mode 100644 index 000000000..784a5469b --- /dev/null +++ b/test/test_suite2/initializer_lists/zero_init.c3t @@ -0,0 +1,69 @@ +// #target: macos-x64 + +union Baz +{ + int x; + double y; +} +struct Bar +{ + int x; + int y; +} + +struct Mega +{ + int[10] z; +} + +fn int test() +{ + Mega m = {}; + int[1] azz = {}; + int[*] a = {}; + Bar b = {}; + Baz z = {}; + int[] sub = {}; + Bar[] foo = {}; + Baz[3] baz = {}; + return 1; +} + +/* #expect: zero_init.ll + + +%Mega = type { [10 x i32] } +%Bar = type { i32, i32 } +%Baz = type { double } + +define i32 @zero_init.test() #0 { +entry: + %m = alloca %Mega, align 4 + %azz = alloca [1 x i32], align 4 + %a = alloca [0 x i32], align 4 + %b = alloca %Bar, align 4 + %z = alloca %Baz, align 8 + %sub = alloca %"int[]", align 8 + %literal = alloca [0 x i32], align 4 + %foo = alloca %"Bar[]", align 8 + %literal1 = alloca [0 x %Bar], align 4 + %baz = alloca [3 x %Baz], align 16 + call void @llvm.memset.p0.i64(ptr align 4 %m, i8 0, i64 40, i1 false) + %0 = getelementptr inbounds [1 x i32], ptr %azz, i64 0, i64 0 + store i32 0, ptr %0, align 4 + %1 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 0 + store i32 0, ptr %1, align 4 + %2 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 1 + store i32 0, ptr %2, align 4 + call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) + store [0 x i32] zeroinitializer, ptr %literal, align 4 + %3 = insertvalue %"int[]" undef, ptr %literal, 0 + %4 = insertvalue %"int[]" %3, i64 0, 1 + store %"int[]" %4, ptr %sub, align 8 + store [0 x %Bar] zeroinitializer, ptr %literal1, align 4 + %5 = insertvalue %"Bar[]" undef, ptr %literal1, 0 + %6 = insertvalue %"Bar[]" %5, i64 0, 1 + store %"Bar[]" %6, ptr %foo, align 8 + call void @llvm.memset.p0.i64(ptr align 16 %baz, i8 0, i64 24, i1 false) + ret i32 1 +} diff --git a/test/test_suite2/lexing/expected_directive.c3 b/test/test_suite2/lexing/expected_directive.c3 new file mode 100644 index 000000000..57f71a053 --- /dev/null +++ b/test/test_suite2/lexing/expected_directive.c3 @@ -0,0 +1,4 @@ +/** +@hello +@param feij > 0 // #error: Expected end of line. +*/ diff --git a/test/test_suite2/lexing/invalid_hex_in_hexarray.c3 b/test/test_suite2/lexing/invalid_hex_in_hexarray.c3 new file mode 100644 index 000000000..536515a37 --- /dev/null +++ b/test/test_suite2/lexing/invalid_hex_in_hexarray.c3 @@ -0,0 +1 @@ +x"abcé" // #error: This isn't a valid hexadecimal digit \ No newline at end of file diff --git a/test/test_suite2/lexing/invalid_hex_in_hexarray2.c3 b/test/test_suite2/lexing/invalid_hex_in_hexarray2.c3 new file mode 100644 index 000000000..eb571c8b2 --- /dev/null +++ b/test/test_suite2/lexing/invalid_hex_in_hexarray2.c3 @@ -0,0 +1 @@ +x"abcg" // #error: 'g' isn't a valid hexadecimal digit \ No newline at end of file diff --git a/test/test_suite2/lexing/no_builtin.c3 b/test/test_suite2/lexing/no_builtin.c3 new file mode 100644 index 000000000..09ff7d6d9 --- /dev/null +++ b/test/test_suite2/lexing/no_builtin.c3 @@ -0,0 +1,2 @@ + +$$1 // #error: Expected a letter after \ No newline at end of file diff --git a/test/test_suite2/literals/bad_bitwidth.c3 b/test/test_suite2/literals/bad_bitwidth.c3 new file mode 100644 index 000000000..e5cf75f34 --- /dev/null +++ b/test/test_suite2/literals/bad_bitwidth.c3 @@ -0,0 +1,4 @@ +int i = 4i15; // #error: Integer type suffix should be i8, i16, i32, i64 or i128 +int j = 4i1024; // #error: Integer type suffix should be i8, i16, i32, i64 or i128 +int k = 4i65536; // #error: Integer type suffix should be i8, i16, i32, i64 or i128 +int l = 4i016; // #error: Integer type suffix should be i8, i16, i32, i64 or i128 \ No newline at end of file diff --git a/test/test_suite2/literals/literal_general.c3t b/test/test_suite2/literals/literal_general.c3t new file mode 100644 index 000000000..377c6096e --- /dev/null +++ b/test/test_suite2/literals/literal_general.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 +module foo; + +int aa = 'ä'; +int x = 'ABCD'; +uint y = 'Helo'; +ushort z = '\x31\x32'; +int d = '\u0031'; +char b = '\x40'; +uint abc = '\U133222AB'; +uint foo = '謝'; + +/* #expect: foo.ll + +@foo.aa = local_unnamed_addr global i32 228, align 4 +@foo.x = local_unnamed_addr global i32 1094861636, align 4 +@foo.y = local_unnamed_addr global i32 1214606447, align 4 +@foo.z = local_unnamed_addr global i16 12594, align 2 +@foo.d = local_unnamed_addr global i32 49, align 4 +@foo.b = local_unnamed_addr global i8 64, align 1 +@foo.abc = local_unnamed_addr global i32 322052779, align 4 +@foo.foo = local_unnamed_addr global i32 35613, align 4 diff --git a/test/test_suite2/literals/multi_unicode.c3 b/test/test_suite2/literals/multi_unicode.c3 new file mode 100644 index 000000000..4d328167c --- /dev/null +++ b/test/test_suite2/literals/multi_unicode.c3 @@ -0,0 +1 @@ +int d = '\u0031\u0032\u0033\u0034'; // #error: can only contain one character \ No newline at end of file diff --git a/test/test_suite2/literals/radix_numbers_errors.c3 b/test/test_suite2/literals/radix_numbers_errors.c3 new file mode 100644 index 000000000..a37970238 --- /dev/null +++ b/test/test_suite2/literals/radix_numbers_errors.c3 @@ -0,0 +1,17 @@ +0o8 // #error: An expression starting with '0o' should be followed by octal numbers (0-7). + +0o% // #error: An expression starting with '0o' should be followed by octal numbers (0-7). + +0o08 // #error: An expression starting with '0o' should be followed by octal numbers (0-7). + +0b2 // #error: An expression starting with '0b' should be followed by binary digits + +0b# // #error: An expression starting with '0b' should be followed by binary digits + +0b12 // #error: An expression starting with '0b' should be followed by binary digits + +0xg // #error: '0x' starts a hexadecimal number, so the next character should be 0-9, a-f or A-F. + +0x! // #error: '0x' starts a hexadecimal number, so the next character should be 0-9, a-f or A-F. + +0b // #error: An expression starting with '0b' should be followed by binary digits diff --git a/test/test_suite2/literals/too_small.c3 b/test/test_suite2/literals/too_small.c3 new file mode 100644 index 000000000..129389d4d --- /dev/null +++ b/test/test_suite2/literals/too_small.c3 @@ -0,0 +1,2 @@ +char aa = 'ä'; +short hmm = '謝'; // #error: unicode character \ No newline at end of file diff --git a/test/test_suite2/macro_methods/access.c3 b/test/test_suite2/macro_methods/access.c3 new file mode 100644 index 000000000..153445d93 --- /dev/null +++ b/test/test_suite2/macro_methods/access.c3 @@ -0,0 +1,35 @@ +struct An1 +{ + An3 x; +} + +struct An3 +{ + An2 y; +} + +struct An2 +{ + int z; +} + +extern fn void printf(char *string); + +macro void An2.@helloWorld(An2 &an2) +{ + printf("An2 hello\n"); +} + +fn void check() +{ + printf("Checking\n"); +} + + +fn void main() +{ + An1 an; + an.x.y.@helloWorld(); + An2 a; + a.@helloWorld(); +} \ No newline at end of file diff --git a/test/test_suite2/macro_methods/macro_method_fails.c3 b/test/test_suite2/macro_methods/macro_method_fails.c3 new file mode 100644 index 000000000..780b4f24f --- /dev/null +++ b/test/test_suite2/macro_methods/macro_method_fails.c3 @@ -0,0 +1,46 @@ +struct An1 +{ + An3 x; +} + +struct An3 +{ + An2 y; +} + +struct An2 +{ + int y; +} + +extern fn void printf(char* string); + +macro void An2.@helloWorld(An2 &an2) +{ + printf("An2 hello\n"); +} + +fn void check() +{ + printf("Checking\n"); +} + + +fn void test1() +{ + An1 an; + an.x.y.@helloWorld; // #error: macro name must be followed by '(' +} + +fn void test2() +{ + An2 a; + a.@helloWorld; // #error: A macro name must be followed by '(' +} + +fn void test3() +{ + An2 a; + a.@helloWorld.b; // #error: There is no member or method 'b' on 'void' +} + diff --git a/test/test_suite2/macro_methods/macro_methods_defined_twice.c3 b/test/test_suite2/macro_methods/macro_methods_defined_twice.c3 new file mode 100644 index 000000000..8bb57cdd0 --- /dev/null +++ b/test/test_suite2/macro_methods/macro_methods_defined_twice.c3 @@ -0,0 +1,31 @@ +module foo; + +struct Bar +{ + int x; +} + +module baz; +import foo; +import std::io; + +macro void foo::Bar.@test(Bar &bar) +{ + io::println("Inside of baz::Bar.test"); +} + +macro void Bar.@test(Bar &bar) // #error: This macro method is already defined in this module +{ + io::println("Inside of baz::Bar.test"); +} + +module abc; +import foo; +import baz; + +fn void main() +{ + Bar bar; + bar.@test(); +} + diff --git a/test/test_suite2/macros/hash_ident.c3 b/test/test_suite2/macros/hash_ident.c3 new file mode 100644 index 000000000..a962d6f0b --- /dev/null +++ b/test/test_suite2/macros/hash_ident.c3 @@ -0,0 +1,24 @@ +macro int @cofefe(#a) +{ + int y = 0; + return #a + #a; +} + +private int abc = 1; + +fn int xx() +{ + abc++; + return abc; +} + +fn void main() +{ + var $x = 0; + int x = 0; + @cofefe(x += 1); + @cofefe(xx()); + @cofefe($x += 1); // #error: Cannot modify '$x' inside of a runtime scope. + @cofefe(y += 1); // #error: 'y' could not be found +} + diff --git a/test/test_suite2/macros/macro_body_as_value.c3 b/test/test_suite2/macros/macro_body_as_value.c3 new file mode 100644 index 000000000..b8df768a4 --- /dev/null +++ b/test/test_suite2/macros/macro_body_as_value.c3 @@ -0,0 +1,12 @@ +macro @foo4(;@body) +{ + @body; // #error: must be followed by () +} + +fn void test() +{ + @foo4() + { + int x = 0; + }; +} \ No newline at end of file diff --git a/test/test_suite2/macros/macro_body_defer.c3t b/test/test_suite2/macros/macro_body_defer.c3t new file mode 100644 index 000000000..5b5c69883 --- /dev/null +++ b/test/test_suite2/macros/macro_body_defer.c3t @@ -0,0 +1,126 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*,...); + +fn int! foo() { return 1; } + +macro @foo_test(int i; @body()) +{ + defer printf("%d\n", i); + @body(); + defer printf("2:%d\n", i); +} + +macro foo_defer() +{ + defer printf("A\n"); + printf("B\n"); + defer printf("C\n"); +} +fn void! main() +{ + foo_defer(); + @foo_test(34) { + defer printf("inside_defer\n"); + }; + while (1) + { + defer printf("outside\n"); + @foo_test(3) + { + defer printf("Inside will it jump?\n"); + printf("3-test\n"); + break; + }; + } + while (1) + { + defer printf("outside2\n"); + printf("--\n"); + @foo_test(3) + { + defer printf("Inside will it jump?\n"); + printf("--3\n"); + return; + }; + } + printf("Should not reach\n"); +} + +/* #expect: foo.ll + +define i64 @foo.foo(ptr %0) #0 { +entry: + %reterr = alloca i64, align 8 + store i32 1, ptr %0, align 4 + ret i64 0 +} + +define i64 @foo.main() #0 { +entry: + %i = alloca i32, align 4 + %i1 = alloca i32, align 4 + %i3 = alloca i32, align 4 + %reterr = alloca i64, align 8 + %reterr5 = alloca i64, align 8 + call void (ptr, ...) @printf(ptr @.str) + call void (ptr, ...) @printf(ptr @.str.1) + call void (ptr, ...) @printf(ptr @.str.2) + store i32 34, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.3) + %0 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %0) + %1 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %1) + br label %loop.body + +loop.body: ; preds = %entry + store i32 3, ptr %i1, align 4 + call void (ptr, ...) @printf(ptr @.str.6) + call void (ptr, ...) @printf(ptr @.str.7) + %2 = load i32, ptr %i1, align 4 + call void (ptr, ...) @printf(ptr @.str.8, i32 %2) + call void (ptr, ...) @printf(ptr @.str.9) + br label %loop.exit + +loop.exit: ; preds = %loop.body + br label %loop.body2 + +loop.body2: ; preds = %loop.exit + call void (ptr, ...) @printf(ptr @.str.13) + store i32 3, ptr %i3, align 4 + call void (ptr, ...) @printf(ptr @.str.14) + call void (ptr, ...) @printf(ptr @.str.15) + %3 = load i32, ptr %i3, align 4 + call void (ptr, ...) @printf(ptr @.str.16, i32 %3) + call void (ptr, ...) @printf(ptr @.str.17) + ret i64 0 + +loop.exit4: ; No predecessors! + call void (ptr, ...) @printf(ptr @.str.21) + ret i64 0 +} + +; Function Attrs: nounwind +define i32 @main(i32 %0, ptr %1) #0 { +entry: + %2 = call i64 @foo.main() + %not_err = icmp eq i64 %2, 0 + br i1 %not_err, label %after.errcheck, label %error_block + +after.errcheck: ; preds = %entry + br label %noerr_block + +noerr_block: ; preds = %after.errcheck + br label %phi_trycatch_block + +error_block: ; preds = %entry + br label %phi_trycatch_block + +phi_trycatch_block: ; preds = %error_block, %noerr_block + %val = phi i8 [ 1, %noerr_block ], [ 0, %error_block ] + %3 = trunc i8 %val to i1 + %not = xor i1 %3, true + %boolsi = zext i1 %not to i32 + ret i32 %boolsi +} \ No newline at end of file diff --git a/test/test_suite2/macros/macro_body_errors.c3 b/test/test_suite2/macros/macro_body_errors.c3 new file mode 100644 index 000000000..de4de1fa2 --- /dev/null +++ b/test/test_suite2/macros/macro_body_errors.c3 @@ -0,0 +1,7 @@ + +macro foo1(;) { } // #error: Expected an ending ')' or a block parameter on the + +macro foo2(;@body()) {} + +macro foo3(;@body) {} + diff --git a/test/test_suite2/macros/macro_calls_prefix.c3 b/test/test_suite2/macros/macro_calls_prefix.c3 new file mode 100644 index 000000000..316bdca8b --- /dev/null +++ b/test/test_suite2/macros/macro_calls_prefix.c3 @@ -0,0 +1,11 @@ +macro foo(a, $b, $Type) {} + +macro @foo2(a, $b, $Type) {} + +macro bar(&x) // #error: non-function +{} + +macro baz(#y) {} // #error: non-function + +macro baz2(a; @body()) {} // #error: non-function + diff --git a/test/test_suite2/macros/macro_common.c3t b/test/test_suite2/macros/macro_common.c3t new file mode 100644 index 000000000..925b08013 --- /dev/null +++ b/test/test_suite2/macros/macro_common.c3t @@ -0,0 +1,52 @@ +module test; + +macro frab(x) +{ + if (!x) return 0; + return 0.0; +} + +fn void test2() +{ + frab(1); + frab(0); +} + +/* #expect: test.ll + +define void @test.test2() #0 { +entry: + %x = alloca i32, align 4 + %blockret = alloca double, align 8 + %x1 = alloca i32, align 4 + %blockret2 = alloca double, align 8 + store i32 1, ptr %x, align 4 + %0 = load i32, ptr %x, align 4 + %not = icmp eq i32 %0, 0 + br i1 %not, label %if.then, label %if.exit + +if.then: ; preds = %entry + store double 0.000000e+00, ptr %blockret, align 8 + br label %expr_block.exit + +if.exit: ; preds = %entry + store double 0.000000e+00, ptr %blockret, align 8 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.exit, %if.then + store i32 0, ptr %x1, align 4 + %1 = load i32, ptr %x1, align 4 + %not3 = icmp eq i32 %1, 0 + br i1 %not3, label %if.then4, label %if.exit5 + +if.then4: ; preds = %expr_block.exit + store double 0.000000e+00, ptr %blockret2, align 8 + br label %expr_block.exit6 + +if.exit5: ; preds = %expr_block.exit + store double 0.000000e+00, ptr %blockret2, align 8 + br label %expr_block.exit6 + +expr_block.exit6: ; preds = %if.exit5, %if.then4 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/macros/macro_convert_literal.c3 b/test/test_suite2/macros/macro_convert_literal.c3 new file mode 100644 index 000000000..25d7900c6 --- /dev/null +++ b/test/test_suite2/macros/macro_convert_literal.c3 @@ -0,0 +1,12 @@ +module foo; +import libc; + +macro foo(y) +{ + return y * y; +} + +fn void main() +{ + libc::printf("%d\n", foo(10)); +} \ No newline at end of file diff --git a/test/test_suite2/macros/macro_defer_exit.c3t b/test/test_suite2/macros/macro_defer_exit.c3t new file mode 100644 index 000000000..207c9ecf8 --- /dev/null +++ b/test/test_suite2/macros/macro_defer_exit.c3t @@ -0,0 +1,83 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*,...); + +macro int abc(x) +{ + defer printf("Out x %d\n", x); + x *= 2; + if (x > 100) return x = x - 100; + printf("Normal end\n"); + return x; +} + +fn void main() +{ + defer printf("On exit\n"); + abc(123); + abc(3); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca i32, align 4 + %blockret = alloca i32, align 4 + %x1 = alloca i32, align 4 + %blockret2 = alloca i32, align 4 + store i32 123, ptr %x, align 4 + %0 = load i32, ptr %x, align 4 + %mul = mul i32 %0, 2 + store i32 %mul, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %gt = icmp sgt i32 %1, 100 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %2 = load i32, ptr %x, align 4 + %sub = sub i32 %2, 100 + store i32 %sub, ptr %x, align 4 + %3 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %3) + store i32 %sub, ptr %blockret, align 4 + br label %expr_block.exit + +if.exit: ; preds = %entry + call void (ptr, ...) @printf(ptr @.str.1) + %4 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %4) + %5 = load i32, ptr %x, align 4 + store i32 %5, ptr %blockret, align 4 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.exit, %if.then + store i32 3, ptr %x1, align 4 + %6 = load i32, ptr %x1, align 4 + %mul3 = mul i32 %6, 2 + store i32 %mul3, ptr %x1, align 4 + %7 = load i32, ptr %x1, align 4 + %gt4 = icmp sgt i32 %7, 100 + br i1 %gt4, label %if.then5, label %if.exit7 + +if.then5: ; preds = %expr_block.exit + %8 = load i32, ptr %x1, align 4 + %sub6 = sub i32 %8, 100 + store i32 %sub6, ptr %x1, align 4 + %9 = load i32, ptr %x1, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %9) + store i32 %sub6, ptr %blockret2, align 4 + br label %expr_block.exit8 + +if.exit7: ; preds = %expr_block.exit + call void (ptr, ...) @printf(ptr @.str.4) + %10 = load i32, ptr %x1, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %10) + %11 = load i32, ptr %x1, align 4 + store i32 %11, ptr %blockret2, align 4 + br label %expr_block.exit8 + +expr_block.exit8: ; preds = %if.exit7, %if.then5 + call void (ptr, ...) @printf(ptr @.str.6) + ret void +} diff --git a/test/test_suite2/macros/macro_defer_scope.c3t b/test/test_suite2/macros/macro_defer_scope.c3t new file mode 100644 index 000000000..0fb766794 --- /dev/null +++ b/test/test_suite2/macros/macro_defer_scope.c3t @@ -0,0 +1,43 @@ +// #target: macos-x64 +module foo; +macro int @cofefe(#a) +{ + int x = 0; + defer printf("Was here\n"); + return #a + #a; +} + +extern fn int printf(char *, ...); + +fn void main() +{ + int x = 0; + @cofefe(x += 1); + printf("%d\n", x); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca i32, align 4 + %blockret = alloca i32, align 4 + %x1 = alloca i32, align 4 + store i32 0, ptr %x, align 4 + store i32 0, ptr %x1, align 4 + %0 = load i32, ptr %x, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %add2 = add i32 %1, 1 + store i32 %add2, ptr %x, align 4 + %add3 = add i32 %add, %add2 + %2 = call i32 (ptr, ...) @printf(ptr @.str) + store i32 %add3, ptr %blockret, align 4 + br label %expr_block.exit + +expr_block.exit: ; preds = %entry + %3 = load i32, ptr %x, align 4 + %4 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %3) + ret void +} diff --git a/test/test_suite2/macros/macro_defer_with_body.c3t b/test/test_suite2/macros/macro_defer_with_body.c3t new file mode 100644 index 000000000..17059c5c0 --- /dev/null +++ b/test/test_suite2/macros/macro_defer_with_body.c3t @@ -0,0 +1,55 @@ +module foo; +macro int @cofefe(a; @body(x)) +{ + @body(a); + @body(a); + return 1; +} + +extern fn int printf(char *, ...); + +fn void main() +{ + int x = 0; + @cofefe(1; int y) + { + defer printf("defer: %d\n", x++); + printf("%d\n", x++); + }; + printf("Done!\n"); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca i32, align 4 + %a = alloca i32, align 4 + %y = alloca i32, align 4 + store i32 0, ptr %x, align 4 + store i32 1, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + store i32 %0, ptr %y, align 4 + %1 = load i32, ptr %x, align 4 + %add = add i32 %1, 1 + store i32 %add, ptr %x, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str, i32 %1) + %3 = load i32, ptr %x, align 4 + %add1 = add i32 %3, 1 + store i32 %add1, ptr %x, align 4 + %4 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %3) + %5 = load i32, ptr %a, align 4 + store i32 %5, ptr %y, align 4 + %6 = load i32, ptr %x, align 4 + %add2 = add i32 %6, 1 + store i32 %add2, ptr %x, align 4 + %7 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %6) + %8 = load i32, ptr %x, align 4 + %add3 = add i32 %8, 1 + store i32 %add3, ptr %x, align 4 + %9 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 %8) + %10 = call i32 (ptr, ...) @printf(ptr @.str.4) + ret void +} + + diff --git a/test/test_suite2/macros/macro_import_res_private.c3t b/test/test_suite2/macros/macro_import_res_private.c3t new file mode 100644 index 000000000..a5f6bce35 --- /dev/null +++ b/test/test_suite2/macros/macro_import_res_private.c3t @@ -0,0 +1,26 @@ +// #target: macos-x64 +module foo; +private fn void foo1() +{} + +module bar; +import private foo; +macro bar1() +{ + foo::foo1(); +} + +module baz; +import bar; +fn void test() +{ + bar::bar1(); +} + +/* #expect: baz.ll + +define void @baz.test() #0 { +entry: + call void @foo.foo1() + ret void +} \ No newline at end of file diff --git a/test/test_suite2/macros/macro_import_resolution.c3 b/test/test_suite2/macros/macro_import_resolution.c3 new file mode 100644 index 000000000..1772389fd --- /dev/null +++ b/test/test_suite2/macros/macro_import_resolution.c3 @@ -0,0 +1,13 @@ +module foo; +import bar; +fn void run() +{ + bar::test(); +} + +module bar; +import baz; +macro test() { baz::test(); } + +module baz; +fn void test() {} \ No newline at end of file diff --git a/test/test_suite2/macros/macro_nested_labels.c3t b/test/test_suite2/macros/macro_nested_labels.c3t new file mode 100644 index 000000000..28989b76d --- /dev/null +++ b/test/test_suite2/macros/macro_nested_labels.c3t @@ -0,0 +1,356 @@ +module test; + +extern fn void printf(char *string, ...); + +macro checker(int x, $i) +{ + var $indent = 3 - $i; + for (int i = 0; i < $indent; i++) printf(" "); + printf("Enter %d\n", $i); + while FOO: (x-- > 0) + { + for (int i = 0; i < $indent; i++) printf(" "); + printf("Helo %d\n", x); + $if ($i > 0): + checker(x, $i - 1); + $endif; + if (x % 2 == 0) break FOO; + } + for (int i = 0; i < $indent; i++) printf(" "); + printf("Exit %d\n", $i); +} + +fn void main() +{ + int ab = 7; + checker(ab, 3); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %ab = alloca i32, align 4 + %x = alloca i32, align 4 + %i = alloca i32, align 4 + %i3 = alloca i32, align 4 + %x9 = alloca i32, align 4 + %i10 = alloca i32, align 4 + %i20 = alloca i32, align 4 + %x26 = alloca i32, align 4 + %i27 = alloca i32, align 4 + %i37 = alloca i32, align 4 + %x43 = alloca i32, align 4 + %i44 = alloca i32, align 4 + %i54 = alloca i32, align 4 + %i61 = alloca i32, align 4 + %i72 = alloca i32, align 4 + %i83 = alloca i32, align 4 + %i94 = alloca i32, align 4 + store i32 7, ptr %ab, align 4 + %0 = load i32, ptr %ab, align 4 + store i32 %0, ptr %x, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %1 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %1, 0 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + call void (ptr, ...) @printf(ptr @.str) + %2 = load i32, ptr %i, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + call void (ptr, ...) @printf(ptr @.str.1, i32 3) + br label %loop.cond1 + +loop.cond1: ; preds = %if.exit92, %loop.exit + %3 = load i32, ptr %x, align 4 + %sub = sub i32 %3, 1 + store i32 %sub, ptr %x, align 4 + %gt = icmp sgt i32 %3, 0 + br i1 %gt, label %loop.body2, label %loop.exit93 + +loop.body2: ; preds = %loop.cond1 + store i32 0, ptr %i3, align 4 + br label %loop.cond4 + +loop.cond4: ; preds = %loop.body6, %loop.body2 + %4 = load i32, ptr %i3, align 4 + %lt5 = icmp slt i32 %4, 0 + br i1 %lt5, label %loop.body6, label %loop.exit8 + +loop.body6: ; preds = %loop.cond4 + call void (ptr, ...) @printf(ptr @.str.2) + %5 = load i32, ptr %i3, align 4 + %add7 = add i32 %5, 1 + store i32 %add7, ptr %i3, align 4 + br label %loop.cond4 + +loop.exit8: ; preds = %loop.cond4 + %6 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %6) + %7 = load i32, ptr %x, align 4 + store i32 %7, ptr %x9, align 4 + store i32 0, ptr %i10, align 4 + br label %loop.cond11 + +loop.cond11: ; preds = %loop.body13, %loop.exit8 + %8 = load i32, ptr %i10, align 4 + %lt12 = icmp slt i32 %8, 1 + br i1 %lt12, label %loop.body13, label %loop.exit15 + +loop.body13: ; preds = %loop.cond11 + call void (ptr, ...) @printf(ptr @.str.4) + %9 = load i32, ptr %i10, align 4 + %add14 = add i32 %9, 1 + store i32 %add14, ptr %i10, align 4 + br label %loop.cond11 + +loop.exit15: ; preds = %loop.cond11 + call void (ptr, ...) @printf(ptr @.str.5, i32 2) + br label %loop.cond16 + +loop.cond16: ; preds = %if.exit81, %loop.exit15 + %10 = load i32, ptr %x9, align 4 + %sub17 = sub i32 %10, 1 + store i32 %sub17, ptr %x9, align 4 + %gt18 = icmp sgt i32 %10, 0 + br i1 %gt18, label %loop.body19, label %loop.exit82 + +loop.body19: ; preds = %loop.cond16 + store i32 0, ptr %i20, align 4 + br label %loop.cond21 + +loop.cond21: ; preds = %loop.body23, %loop.body19 + %11 = load i32, ptr %i20, align 4 + %lt22 = icmp slt i32 %11, 1 + br i1 %lt22, label %loop.body23, label %loop.exit25 + +loop.body23: ; preds = %loop.cond21 + call void (ptr, ...) @printf(ptr @.str.6) + %12 = load i32, ptr %i20, align 4 + %add24 = add i32 %12, 1 + store i32 %add24, ptr %i20, align 4 + br label %loop.cond21 + +loop.exit25: ; preds = %loop.cond21 + %13 = load i32, ptr %x9, align 4 + call void (ptr, ...) @printf(ptr @.str.7, i32 %13) + %14 = load i32, ptr %x9, align 4 + store i32 %14, ptr %x26, align 4 + store i32 0, ptr %i27, align 4 + br label %loop.cond28 + +loop.cond28: ; preds = %loop.body30, %loop.exit25 + %15 = load i32, ptr %i27, align 4 + %lt29 = icmp slt i32 %15, 2 + br i1 %lt29, label %loop.body30, label %loop.exit32 + +loop.body30: ; preds = %loop.cond28 + call void (ptr, ...) @printf(ptr @.str.8) + %16 = load i32, ptr %i27, align 4 + %add31 = add i32 %16, 1 + store i32 %add31, ptr %i27, align 4 + br label %loop.cond28 + +loop.exit32: ; preds = %loop.cond28 + call void (ptr, ...) @printf(ptr @.str.9, i32 1) + br label %loop.cond33 + +loop.cond33: ; preds = %if.exit70, %loop.exit32 + %17 = load i32, ptr %x26, align 4 + %sub34 = sub i32 %17, 1 + store i32 %sub34, ptr %x26, align 4 + %gt35 = icmp sgt i32 %17, 0 + br i1 %gt35, label %loop.body36, label %loop.exit71 + +loop.body36: ; preds = %loop.cond33 + store i32 0, ptr %i37, align 4 + br label %loop.cond38 + +loop.cond38: ; preds = %loop.body40, %loop.body36 + %18 = load i32, ptr %i37, align 4 + %lt39 = icmp slt i32 %18, 2 + br i1 %lt39, label %loop.body40, label %loop.exit42 + +loop.body40: ; preds = %loop.cond38 + call void (ptr, ...) @printf(ptr @.str.10) + %19 = load i32, ptr %i37, align 4 + %add41 = add i32 %19, 1 + store i32 %add41, ptr %i37, align 4 + br label %loop.cond38 + +loop.exit42: ; preds = %loop.cond38 + %20 = load i32, ptr %x26, align 4 + call void (ptr, ...) @printf(ptr @.str.11, i32 %20) + %21 = load i32, ptr %x26, align 4 + store i32 %21, ptr %x43, align 4 + store i32 0, ptr %i44, align 4 + br label %loop.cond45 + +loop.cond45: ; preds = %loop.body47, %loop.exit42 + %22 = load i32, ptr %i44, align 4 + %lt46 = icmp slt i32 %22, 3 + br i1 %lt46, label %loop.body47, label %loop.exit49 + +loop.body47: ; preds = %loop.cond45 + call void (ptr, ...) @printf(ptr @.str.12) + %23 = load i32, ptr %i44, align 4 + %add48 = add i32 %23, 1 + store i32 %add48, ptr %i44, align 4 + br label %loop.cond45 + +loop.exit49: ; preds = %loop.cond45 + call void (ptr, ...) @printf(ptr @.str.13, i32 0) + br label %loop.cond50 + +loop.cond50: ; preds = %if.exit, %loop.exit49 + %24 = load i32, ptr %x43, align 4 + %sub51 = sub i32 %24, 1 + store i32 %sub51, ptr %x43, align 4 + %gt52 = icmp sgt i32 %24, 0 + br i1 %gt52, label %loop.body53, label %loop.exit60 + +loop.body53: ; preds = %loop.cond50 + store i32 0, ptr %i54, align 4 + br label %loop.cond55 + +loop.cond55: ; preds = %loop.body57, %loop.body53 + %25 = load i32, ptr %i54, align 4 + %lt56 = icmp slt i32 %25, 3 + br i1 %lt56, label %loop.body57, label %loop.exit59 + +loop.body57: ; preds = %loop.cond55 + call void (ptr, ...) @printf(ptr @.str.14) + %26 = load i32, ptr %i54, align 4 + %add58 = add i32 %26, 1 + store i32 %add58, ptr %i54, align 4 + br label %loop.cond55 + +loop.exit59: ; preds = %loop.cond55 + %27 = load i32, ptr %x43, align 4 + call void (ptr, ...) @printf(ptr @.str.15, i32 %27) + %28 = load i32, ptr %x43, align 4 + %smod = srem i32 %28, 2 + %eq = icmp eq i32 %smod, 0 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.exit59 + br label %loop.exit60 + +if.exit: ; preds = %loop.exit59 + br label %loop.cond50 + +loop.exit60: ; preds = %if.then, %loop.cond50 + store i32 0, ptr %i61, align 4 + br label %loop.cond62 + +loop.cond62: ; preds = %loop.body64, %loop.exit60 + %29 = load i32, ptr %i61, align 4 + %lt63 = icmp slt i32 %29, 3 + br i1 %lt63, label %loop.body64, label %loop.exit66 + +loop.body64: ; preds = %loop.cond62 + call void (ptr, ...) @printf(ptr @.str.16) + %30 = load i32, ptr %i61, align 4 + %add65 = add i32 %30, 1 + store i32 %add65, ptr %i61, align 4 + br label %loop.cond62 + +loop.exit66: ; preds = %loop.cond62 + call void (ptr, ...) @printf(ptr @.str.17, i32 0) + %31 = load i32, ptr %x26, align 4 + %smod67 = srem i32 %31, 2 + %eq68 = icmp eq i32 %smod67, 0 + br i1 %eq68, label %if.then69, label %if.exit70 + +if.then69: ; preds = %loop.exit66 + br label %loop.exit71 + +if.exit70: ; preds = %loop.exit66 + br label %loop.cond33 + +loop.exit71: ; preds = %if.then69, %loop.cond33 + store i32 0, ptr %i72, align 4 + br label %loop.cond73 + +loop.cond73: ; preds = %loop.body75, %loop.exit71 + %32 = load i32, ptr %i72, align 4 + %lt74 = icmp slt i32 %32, 2 + br i1 %lt74, label %loop.body75, label %loop.exit77 + +loop.body75: ; preds = %loop.cond73 + call void (ptr, ...) @printf(ptr @.str.18) + %33 = load i32, ptr %i72, align 4 + %add76 = add i32 %33, 1 + store i32 %add76, ptr %i72, align 4 + br label %loop.cond73 + +loop.exit77: ; preds = %loop.cond73 + call void (ptr, ...) @printf(ptr @.str.19, i32 1) + %34 = load i32, ptr %x9, align 4 + %smod78 = srem i32 %34, 2 + %eq79 = icmp eq i32 %smod78, 0 + br i1 %eq79, label %if.then80, label %if.exit81 + +if.then80: ; preds = %loop.exit77 + br label %loop.exit82 + +if.exit81: ; preds = %loop.exit77 + br label %loop.cond16 + +loop.exit82: ; preds = %if.then80, %loop.cond16 + store i32 0, ptr %i83, align 4 + br label %loop.cond84 + +loop.cond84: ; preds = %loop.body86, %loop.exit82 + %35 = load i32, ptr %i83, align 4 + %lt85 = icmp slt i32 %35, 1 + br i1 %lt85, label %loop.body86, label %loop.exit88 + +loop.body86: ; preds = %loop.cond84 + call void (ptr, ...) @printf(ptr @.str.20) + %36 = load i32, ptr %i83, align 4 + %add87 = add i32 %36, 1 + store i32 %add87, ptr %i83, align 4 + br label %loop.cond84 + +loop.exit88: ; preds = %loop.cond84 + call void (ptr, ...) @printf(ptr @.str.21, i32 2) + %37 = load i32, ptr %x, align 4 + %smod89 = srem i32 %37, 2 + %eq90 = icmp eq i32 %smod89, 0 + br i1 %eq90, label %if.then91, label %if.exit92 + +if.then91: ; preds = %loop.exit88 + br label %loop.exit93 + +if.exit92: ; preds = %loop.exit88 + br label %loop.cond1 + +loop.exit93: ; preds = %if.then91, %loop.cond1 + store i32 0, ptr %i94, align 4 + br label %loop.cond95 + +loop.cond95: ; preds = %loop.body97, %loop.exit93 + %38 = load i32, ptr %i94, align 4 + %lt96 = icmp slt i32 %38, 0 + br i1 %lt96, label %loop.body97, label %loop.exit99 + +loop.body97: ; preds = %loop.cond95 + call void (ptr, ...) @printf(ptr @.str.22) + %39 = load i32, ptr %i94, align 4 + %add98 = add i32 %39, 1 + store i32 %add98, ptr %i94, align 4 + br label %loop.cond95 + +loop.exit99: ; preds = %loop.cond95 + call void (ptr, ...) @printf(ptr @.str.23, i32 3) + ret void +} diff --git a/test/test_suite2/macros/macro_resolution.c3 b/test/test_suite2/macros/macro_resolution.c3 new file mode 100644 index 000000000..37f80b138 --- /dev/null +++ b/test/test_suite2/macros/macro_resolution.c3 @@ -0,0 +1,24 @@ +module foo; +import bar; +fn void run() +{ + bar::test(); +} + +fn void run2() +{ + bar::test2(); +} + +private fn void tester() {} + +module bar; +macro test() +{ + tester(); // #error: 'tester' could not be found, did you spell it right +} + +macro test2() +{ + foo::tester(); // #error: 'foo::tester' could not be found, did you spell +} diff --git a/test/test_suite2/macros/macro_rtype.c3 b/test/test_suite2/macros/macro_rtype.c3 new file mode 100644 index 000000000..8a32d3490 --- /dev/null +++ b/test/test_suite2/macros/macro_rtype.c3 @@ -0,0 +1,9 @@ +macro int frob() +{ + return 0.0; // #error: Implicitly casting 'double' to 'int' is not permitted +} + +fn void test1() +{ + frob(); +} \ No newline at end of file diff --git a/test/test_suite2/macros/macro_with_body.c3t b/test/test_suite2/macros/macro_with_body.c3t new file mode 100644 index 000000000..6eacc83ee --- /dev/null +++ b/test/test_suite2/macros/macro_with_body.c3t @@ -0,0 +1,106 @@ +module withbody; + + +extern fn int printf(char *, ...); + +struct Foo +{ + int x; +} + +fn int Foo.mutate(Foo *foo) +{ + printf("Mutating\n"); + return 10 * ++foo.x; +} + +macro @macro_with_body(foo, &x; @body(x, y)) +{ + x = foo.x; + @body(foo.mutate(), x); +} + +macro @repeat(int times; @body(x)) +{ + for (int i = 0; i < times; i++) + { + @body(i + 1); + } +} + +fn void main() +{ + Foo f = { 33 }; + int y; + @macro_with_body(f, y; int x, int dy) + { + printf("Got values %d, %d\n", x, dy); + }; + @repeat(10; int loop) + { + printf("Repeat %d\n", loop); + }; + +} + +/* #expect: withbody.ll + +define i32 @withbody.Foo__mutate(ptr %0) #0 { +entry: + %1 = call i32 (ptr, ...) @printf(ptr @.str.2) + %2 = getelementptr inbounds %Foo, ptr %0, i32 0, i32 0 + %3 = load i32, ptr %2, align 8 + %add = add i32 %3, 1 + store i32 %add, ptr %2, align 8 + %mul = mul i32 10, %add + ret i32 %mul +} + +define void @withbody.main() #0 { +entry: + %f = alloca %Foo, align 4 + %y = alloca i32, align 4 + %foo = alloca %Foo, align 4 + %x = alloca i32, align 4 + %dy = alloca i32, align 4 + %times = alloca i32, align 4 + %i = alloca i32, align 4 + %loop = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %f, ptr align 4 @.__const, i32 4, i1 false) + store i32 0, ptr %y, align 4 + %0 = load %Foo, ptr %f, align 4 + store %Foo %0, ptr %foo, align 4 + %1 = getelementptr inbounds %Foo, ptr %foo, i32 0, i32 0 + %2 = load i32, ptr %1, align 4 + store i32 %2, ptr %y, align 4 + %3 = call i32 @withbody.Foo__mutate(ptr %foo) + store i32 %3, ptr %x, align 4 + %4 = load i32, ptr %y, align 4 + store i32 %4, ptr %dy, align 4 + %5 = load i32, ptr %x, align 4 + %6 = load i32, ptr %dy, align 4 + %7 = call i32 (ptr, ...) @printf(ptr @.str, i32 %5, i32 %6) + store i32 10, ptr %times, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %8 = load i32, ptr %i, align 4 + %9 = load i32, ptr %times, align 4 + %lt = icmp slt i32 %8, %9 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %10 = load i32, ptr %i, align 4 + %add = add i32 %10, 1 + store i32 %add, ptr %loop, align 4 + %11 = load i32, ptr %loop, align 4 + %12 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %11) + %13 = load i32, ptr %i, align 4 + %add1 = add i32 %13, 1 + store i32 %add1, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} diff --git a/test/test_suite2/macros/no_body.c3 b/test/test_suite2/macros/no_body.c3 new file mode 100644 index 000000000..6a71cf27f --- /dev/null +++ b/test/test_suite2/macros/no_body.c3 @@ -0,0 +1,50 @@ +module test; + +extern fn int printf(char *, ...); + +macro @foo(x; @body(y)) +{ + @body(x); +} + +fn void test() +{ + @foo(10); // #error: Expected call to have a trailing statement, did you forget to add it? +} + +fn void test3() +{ + @foo(10) // #error: Not enough parameters + { + }; +} + +fn void test5() +{ + @foo(10; int a, int b) // #error: Too many parameters for the macro body, expected + { + }; +} +macro foo_no(x) +{ + return x; +} + +fn void test2() +{ + foo_no(10) // #error: This macro does not support trailing statements + { + printf("foek"); + }; +} + +macro foo2(x) +{ + @body(x); // #error: '@body' could not be found, did you spell it right? +} + +fn void test4() +{ + foo2(10); +} + diff --git a/test/test_suite2/macros/type_params.c3t b/test/test_suite2/macros/type_params.c3t new file mode 100644 index 000000000..1430897b6 --- /dev/null +++ b/test/test_suite2/macros/type_params.c3t @@ -0,0 +1,42 @@ +// #target: macos-x64 +macro foo($Foo) +{ + $Foo a; + return a; +} + +define Bar = short; +fn void test() +{ + int x = foo(int); + var $Foo = double; + double d = foo($Foo); + double d2 = foo($typeof(d)); + short z = foo(Bar); +} + + +/* #expect: type_params.ll + + %x = alloca i32, align 4 + %a = alloca i32, align 4 + %d = alloca double, align 8 + %a1 = alloca double, align 8 + %d2 = alloca double, align 8 + %a2 = alloca double, align 8 + %z = alloca i16, align 2 + %a3 = alloca i16, align 2 + store i32 0, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + store i32 %0, ptr %x, align 4 + store double 0.000000e+00, ptr %a1, align 8 + %1 = load double, ptr %a1, align 8 + store double %1, ptr %d, align 8 + store double 0.000000e+00, ptr %a2, align 8 + %2 = load double, ptr %a2, align 8 + store double %2, ptr %d2, align 8 + store i16 0, ptr %a3, align 2 + %3 = load i16, ptr %a3, align 2 + store i16 %3, ptr %z, align 2 + ret void +} diff --git a/test/test_suite2/macros/userland_bitcast.c3t b/test/test_suite2/macros/userland_bitcast.c3t new file mode 100644 index 000000000..d3214484a --- /dev/null +++ b/test/test_suite2/macros/userland_bitcast.c3t @@ -0,0 +1,332 @@ +// #target: macos-x64 + +macro testbitcast(expr, $Type) +{ + $assert($sizeof(expr) == $Type.sizeof, "Cannot bitcast between types of different size."); + $Type x = void; + var $size = (usize)($sizeof(expr)); + + $if ($alignof(expr) >= 8 && $alignof($Type) >= 8): + ulong *b = (ulong*)(&expr); + ulong *to = (ulong*)(&x); + for (usize i = 0; i < $size; i += 8) + { + to[i] = b[i]; + } + $elif ($alignof(expr) >= 4 && $alignof($Type) >= 4): + uint* b = (uint*)(&expr); + uint* to = (uint*)(&x); + for (usize i = 0; i < $size; i += 4) + { + to[i] = b[i]; + } + $elif ($alignof(expr) >= 2 && $alignof($Type) >= 2): + ushort* b = (ushort*)(&expr); + ushort* to = (ushort*)(&x); + for (usize i = 0; i < $size; i += 2) + { + to[i] = b[i]; + } + $else: + char* b = (char*)(&expr); + char* to = (char*)(&x); + for (usize i = 0; i < $size; i++) + { + to[i] = b[i]; + } + $endif; + return x; +} + +extern fn void printf(char*, ...); + +struct Foo +{ + short a; + char b; + char c; + short d; + short e; +} + +fn ulong testFoo(short x) +{ + Foo z; + z.a = x; + return testbitcast(z, ulong); +} + +fn char[4] test(float x) +{ + return testbitcast(x, char[4]); +} + +fn void main() +{ + float f = 12.353; + int i = testbitcast(f, int); + float f2 = testbitcast(i, float); + printf("%f => %d => %f\n", f, i, f2); + double d = 12.353e267; + ulong l = testbitcast(d, ulong); + double d2 = testbitcast(d, double); + printf("%e => %llu => %e\n", d, l, d2); + +} + +/* #expect: userland_bitcast.ll + +%Foo = type { i16, i8, i8, i16, i16 } + +@.typeid.userland_bitcast.Foo = linkonce constant { i8, i64 } { i8 10, i64 5 }, align 8 +@.str = private unnamed_addr constant [16 x i8] c"%f => %d => %f\0A\00", align 1 +@.str.1 = private unnamed_addr constant [18 x i8] c"%e => %llu => %e\0A\00", align 1 + +define i64 @userland_bitcast.testFoo(i16 signext %0) #0 { +entry: + %z = alloca %Foo, align 2 + %expr = alloca %Foo, align 2 + %x = alloca i64, align 8 + %b = alloca ptr, align 8 + %to = alloca ptr, align 8 + %i = alloca i64, align 8 + %1 = getelementptr inbounds %Foo, ptr %z, i32 0, i32 0 + store i16 0, ptr %1, align 2 + %2 = getelementptr inbounds %Foo, ptr %z, i32 0, i32 1 + store i8 0, ptr %2, align 2 + %3 = getelementptr inbounds %Foo, ptr %z, i32 0, i32 2 + store i8 0, ptr %3, align 1 + %4 = getelementptr inbounds %Foo, ptr %z, i32 0, i32 3 + store i16 0, ptr %4, align 2 + %5 = getelementptr inbounds %Foo, ptr %z, i32 0, i32 4 + store i16 0, ptr %5, align 2 + %6 = getelementptr inbounds %Foo, ptr %z, i32 0, i32 0 + store i16 %0, ptr %6, align 2 + %7 = load %Foo, ptr %z, align 2 + store %Foo %7, ptr %expr, align 2 + store ptr %expr, ptr %b, align 8 + store ptr %x, ptr %to, align 8 + store i64 0, ptr %i, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %8 = load i64, ptr %i, align 8 + %lt = icmp ult i64 %8, 8 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %9 = load ptr, ptr %to, align 8 + %10 = load i64, ptr %i, align 8 + %ptroffset = getelementptr inbounds i16, ptr %9, i64 %10 + %11 = load ptr, ptr %b, align 8 + %12 = load i64, ptr %i, align 8 + %ptroffset1 = getelementptr inbounds i16, ptr %11, i64 %12 + %13 = load i16, ptr %ptroffset1, align 2 + store i16 %13, ptr %ptroffset, align 2 + %14 = load i64, ptr %i, align 8 + %add = add i64 %14, 2 + store i64 %add, ptr %i, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %15 = load i64, ptr %x, align 8 + ret i64 %15 +} + +define i32 @userland_bitcast.test(float %0) #0 { +entry: + %expr = alloca float, align 4 + %x = alloca [4 x i8], align 1 + %b = alloca ptr, align 8 + %to = alloca ptr, align 8 + %i = alloca i64, align 8 + %tempcoerce = alloca i32, align 4 + store float %0, ptr %expr, align 4 + store ptr %expr, ptr %b, align 8 + store ptr %x, ptr %to, align 8 + store i64 0, ptr %i, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %1 = load i64, ptr %i, align 8 + %lt = icmp ult i64 %1, 4 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %2 = load ptr, ptr %to, align 8 + %3 = load i64, ptr %i, align 8 + %ptroffset = getelementptr inbounds i8, ptr %2, i64 %3 + %4 = load ptr, ptr %b, align 8 + %5 = load i64, ptr %i, align 8 + %ptroffset1 = getelementptr inbounds i8, ptr %4, i64 %5 + %6 = load i8, ptr %ptroffset1, align 1 + store i8 %6, ptr %ptroffset, align 1 + %7 = load i64, ptr %i, align 8 + %add = add i64 %7, 1 + store i64 %add, ptr %i, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %tempcoerce, ptr align 1 %x, i32 4, i1 false) + %8 = load i32, ptr %tempcoerce, align 4 + ret i32 %8 +} + +define void @userland_bitcast.main() #0 { +entry: + %f = alloca float, align 4 + %i = alloca i32, align 4 + %expr = alloca float, align 4 + %x = alloca i32, align 4 + %b = alloca ptr, align 8 + %to = alloca ptr, align 8 + %i1 = alloca i64, align 8 + %f2 = alloca float, align 4 + %expr3 = alloca i32, align 4 + %x4 = alloca float, align 4 + %b5 = alloca ptr, align 8 + %to6 = alloca ptr, align 8 + %i7 = alloca i64, align 8 + %d = alloca double, align 8 + %l = alloca i64, align 8 + %expr16 = alloca double, align 8 + %x17 = alloca i64, align 8 + %b18 = alloca ptr, align 8 + %to19 = alloca ptr, align 8 + %i20 = alloca i64, align 8 + %d2 = alloca double, align 8 + %expr28 = alloca double, align 8 + %x29 = alloca double, align 8 + %b30 = alloca ptr, align 8 + %to31 = alloca ptr, align 8 + %i32 = alloca i64, align 8 + store float 0x4028B4BC60000000, ptr %f, align 4 + %0 = load float, ptr %f, align 4 + store float %0, ptr %expr, align 4 + store ptr %expr, ptr %b, align 8 + store ptr %x, ptr %to, align 8 + store i64 0, ptr %i1, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %1 = load i64, ptr %i1, align 8 + %lt = icmp ult i64 %1, 4 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %2 = load ptr, ptr %to, align 8 + %3 = load i64, ptr %i1, align 8 + %ptroffset = getelementptr inbounds i32, ptr %2, i64 %3 + %4 = load ptr, ptr %b, align 8 + %5 = load i64, ptr %i1, align 8 + %ptroffset2 = getelementptr inbounds i32, ptr %4, i64 %5 + %6 = load i32, ptr %ptroffset2, align 4 + store i32 %6, ptr %ptroffset, align 4 + %7 = load i64, ptr %i1, align 8 + %add = add i64 %7, 4 + store i64 %add, ptr %i1, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %8 = load i32, ptr %x, align 4 + store i32 %8, ptr %i, align 4 + %9 = load i32, ptr %i, align 4 + store i32 %9, ptr %expr3, align 4 + store ptr %expr3, ptr %b5, align 8 + store ptr %x4, ptr %to6, align 8 + store i64 0, ptr %i7, align 8 + br label %loop.cond8 + +loop.cond8: ; preds = %loop.body10, %loop.exit + %10 = load i64, ptr %i7, align 8 + %lt9 = icmp ult i64 %10, 4 + br i1 %lt9, label %loop.body10, label %loop.exit14 + +loop.body10: ; preds = %loop.cond8 + %11 = load ptr, ptr %to6, align 8 + %12 = load i64, ptr %i7, align 8 + %ptroffset11 = getelementptr inbounds i32, ptr %11, i64 %12 + %13 = load ptr, ptr %b5, align 8 + %14 = load i64, ptr %i7, align 8 + %ptroffset12 = getelementptr inbounds i32, ptr %13, i64 %14 + %15 = load i32, ptr %ptroffset12, align 4 + store i32 %15, ptr %ptroffset11, align 4 + %16 = load i64, ptr %i7, align 8 + %add13 = add i64 %16, 4 + store i64 %add13, ptr %i7, align 8 + br label %loop.cond8 + +loop.exit14: ; preds = %loop.cond8 + %17 = load float, ptr %x4, align 4 + store float %17, ptr %f2, align 4 + %18 = load float, ptr %f, align 4 + %fpfpext = fpext float %18 to double + %19 = load i32, ptr %i, align 4 + %20 = load float, ptr %f2, align 4 + %fpfpext15 = fpext float %20 to double + call void (ptr, ...) @printf(ptr @.str, double %fpfpext, i32 %19, double %fpfpext15) + store double 1.235300e+268, ptr %d, align 8 + %21 = load double, ptr %d, align 8 + store double %21, ptr %expr16, align 8 + store ptr %expr16, ptr %b18, align 8 + store ptr %x17, ptr %to19, align 8 + br label %loop.cond21 + +loop.cond21: ; preds = %loop.body23, %loop.exit14 + %22 = load i64, ptr %i20, align 8 + %lt22 = icmp ult i64 %22, 8 + br i1 %lt22, label %loop.body23, label %loop.exit27 + +loop.body23: ; preds = %loop.cond21 + %23 = load ptr, ptr %to19, align 8 + %24 = load i64, ptr %i20, align 8 + %ptroffset24 = getelementptr inbounds i64, ptr %23, i64 %24 + %25 = load ptr, ptr %b18, align 8 + %26 = load i64, ptr %i20, align 8 + %ptroffset25 = getelementptr inbounds i64, ptr %25, i64 %26 + %27 = load i64, ptr %ptroffset25, align 8 + store i64 %27, ptr %ptroffset24, align 8 + %28 = load i64, ptr %i20, align 8 + %add26 = add i64 %28, 8 + store i64 %add26, ptr %i20, align 8 + br label %loop.cond21 + +loop.exit27: ; preds = %loop.cond21 + %29 = load i64, ptr %x17, align 8 + store i64 %29, ptr %l, align 8 + %30 = load double, ptr %d, align 8 + store double %30, ptr %expr28, align 8 + store ptr %expr28, ptr %b30, align 8 + store ptr %x29, ptr %to31, align 8 + store i64 0, ptr %i32, align 8 + br label %loop.cond33 + +loop.cond33: ; preds = %loop.body35, %loop.exit27 + %31 = load i64, ptr %i32, align 8 + %lt34 = icmp ult i64 %31, 8 + br i1 %lt34, label %loop.body35, label %loop.exit39 + +loop.body35: ; preds = %loop.cond33 + %32 = load ptr, ptr %to31, align 8 + %33 = load i64, ptr %i32, align 8 + %ptroffset36 = getelementptr inbounds i64, ptr %32, i64 %33 + %34 = load ptr, ptr %b30, align 8 + %35 = load i64, ptr %i32, align 8 + %ptroffset37 = getelementptr inbounds i64, ptr %34, i64 %35 + %36 = load i64, ptr %ptroffset37, align 8 + store i64 %36, ptr %ptroffset36, align 8 + %37 = load i64, ptr %i32, align 8 + %add38 = add i64 %37, 8 + store i64 %add38, ptr %i32, align 8 + br label %loop.cond33 + +loop.exit39: ; preds = %loop.cond33 + %38 = load double, ptr %x29, align 8 + store double %38, ptr %d2, align 8 + %39 = load double, ptr %d, align 8 + %40 = load i64, ptr %l, align 8 + %41 = load double, ptr %d2, align 8 + call void (ptr, ...) @printf(ptr @.str.1, double %39, i64 %40, double %41) + ret void +} + diff --git a/test/test_suite2/methods/access.c3 b/test/test_suite2/methods/access.c3 new file mode 100644 index 000000000..ab3391c11 --- /dev/null +++ b/test/test_suite2/methods/access.c3 @@ -0,0 +1,37 @@ +extern fn void printf(...); + +struct An1 +{ + An3 x; +} + +struct An3 +{ + An2 y; +} + +define AnCall = fn void(); + +struct An2 +{ + AnCall t; +} + +fn void An2.helloWorld(An2 *an2) +{ + printf("An2 hello\n"); +} + +fn void check() +{ + printf("Checking\n"); +} + + +fn void main() +{ + An1 an; + an.x.y.helloWorld(); + an.x.y.t = ✓ + an.x.y.t(); +} \ No newline at end of file diff --git a/test/test_suite2/methods/enum_distinct_err_methods.c3t b/test/test_suite2/methods/enum_distinct_err_methods.c3t new file mode 100644 index 000000000..0cf37cd9c --- /dev/null +++ b/test/test_suite2/methods/enum_distinct_err_methods.c3t @@ -0,0 +1,76 @@ +// #target: macos-x64 + +module foo; +import std::io; + +fault Foo +{ + X +} + +define Bar = distinct int; + +enum MyEnum +{ + A, + B +} + +fn void Foo.hello(Foo *f) +{ + io::println("Hello from Foo"); +} + +fn void Bar.hello(Bar *b) +{ + io::println("Hello from Bar"); +} + +fn void MyEnum.hello(MyEnum *myenum) +{ + io::println("Hello from MyEnum"); +} +fn int main() +{ + Foo f; + Bar b; + MyEnum a = MyEnum.A; + f.hello(); + b.hello(); + a.hello(); + return 0; +} + +/* #expect: foo.ll + +define void @foo.Foo__hello(ptr %0) #0 { +entry: + %1 = call i32 @"std::io.println"(ptr @.str) #1 + ret void +} + +define void @foo.Bar__hello(ptr %0) #0 { +entry: + %1 = call i32 @"std::io.println"(ptr @.str.1) #1 + ret void +} + +define void @foo.MyEnum__hello(ptr %0) #0 { +entry: + %1 = call i32 @"std::io.println"(ptr @.str.2) #1 + ret void +} + +define i32 @main() #0 { +entry: + %f = alloca i64, align 8 + %b = alloca i32, align 4 + %a = alloca i32, align 4 + store i64 0, ptr %f, align 8 + store i32 0, ptr %b, align 4 + store i32 0, ptr %a, align 4 + call void @foo.Foo__hello(ptr %f) + call void @foo.Bar__hello(ptr %b) + call void @foo.MyEnum__hello(ptr %a) + ret i32 0 +} diff --git a/test/test_suite2/methods/extension_method.c3t b/test/test_suite2/methods/extension_method.c3t new file mode 100644 index 000000000..7068bb12c --- /dev/null +++ b/test/test_suite2/methods/extension_method.c3t @@ -0,0 +1,40 @@ +module foo; + +struct Bar +{ + int x; +} + +module baz; +import foo; +import std::io; + +fn void foo::Bar.test(Bar *bar) +{ + io::println("Inside of baz::Bar.test"); +} + +module abc; +import foo; +import baz; + +fn int main() +{ + Bar bar; + bar.test(); + return 0; +} + +/* #expect: abc.ll + +%Bar = type { i32 } + +define i32 @main() #0 { +entry: + %bar = alloca %Bar, align 4 + store i32 0, ptr %bar, align 4 + call void @foo.Bar__test(ptr %bar) + ret i32 0 +} + +declare void @foo.Bar__test(ptr) diff --git a/test/test_suite2/methods/extension_method_already_exist.c3 b/test/test_suite2/methods/extension_method_already_exist.c3 new file mode 100644 index 000000000..beccdbca1 --- /dev/null +++ b/test/test_suite2/methods/extension_method_already_exist.c3 @@ -0,0 +1,30 @@ +module foo; + +fn void Bar.test(Bar *bar) +{ + io::println("Inside of baz::Bar.test"); +} + +struct Bar +{ + int x; +} + +module baz; +import foo; +import std::io; + +fn void foo::Bar.test(Bar *bar) // #error: This method is already defined for 'Bar' +{ + io::println("Inside of baz::Bar.test"); +} + +module abc; +import foo; +import baz; + +fn void main() +{ + Bar bar; + bar.test(); +} \ No newline at end of file diff --git a/test/test_suite2/methods/methods_defined_twice.c3 b/test/test_suite2/methods/methods_defined_twice.c3 new file mode 100644 index 000000000..60d809b6f --- /dev/null +++ b/test/test_suite2/methods/methods_defined_twice.c3 @@ -0,0 +1,31 @@ +module foo; + +struct Bar +{ + int x; +} + +module baz; +import foo; +import std::io; + +fn void foo::Bar.test(Bar *bar) +{ + io::println("Inside of baz::Bar.test"); +} + +fn void Bar.test(Bar *bar) // #error: This method is already defined in this module +{ + io::println("Inside of baz::Bar.test"); +} + +module abc; +import foo; +import baz; + +fn void main() +{ + Bar bar; + bar.test(); +} + diff --git a/test/test_suite2/module/missing_semi.c3 b/test/test_suite2/module/missing_semi.c3 new file mode 100644 index 000000000..ce8ae0942 --- /dev/null +++ b/test/test_suite2/module/missing_semi.c3 @@ -0,0 +1,3 @@ +module test // #error: Expected ';' + +int a; \ No newline at end of file diff --git a/test/test_suite2/module/module_bad_path_ident.c3 b/test/test_suite2/module/module_bad_path_ident.c3 new file mode 100644 index 000000000..3897c998c --- /dev/null +++ b/test/test_suite2/module/module_bad_path_ident.c3 @@ -0,0 +1 @@ +module big::MONEY; // #error: The elements of a module path must consist of only lower \ No newline at end of file diff --git a/test/test_suite2/module/module_bad_path_invalid.c3 b/test/test_suite2/module/module_bad_path_invalid.c3 new file mode 100644 index 000000000..1554c001d --- /dev/null +++ b/test/test_suite2/module/module_bad_path_invalid.c3 @@ -0,0 +1 @@ +module abc::&&; // #error: Each '::' must be followed by a regular lower case sub module name \ No newline at end of file diff --git a/test/test_suite2/module/module_bad_path_keyword.c3 b/test/test_suite2/module/module_bad_path_keyword.c3 new file mode 100644 index 000000000..918aa7389 --- /dev/null +++ b/test/test_suite2/module/module_bad_path_keyword.c3 @@ -0,0 +1 @@ +module abc::if::while; // #error: The module path cannot contain a reserved keyword, try another name \ No newline at end of file diff --git a/test/test_suite2/module/module_error_string.c3 b/test/test_suite2/module/module_error_string.c3 new file mode 100644 index 000000000..ceb869c56 --- /dev/null +++ b/test/test_suite2/module/module_error_string.c3 @@ -0,0 +1 @@ +module "Hello my friend"; // #error: 'module' should be followed by a plain identifier, not a string. Did you accidentally put the module name between ""? \ No newline at end of file diff --git a/test/test_suite2/module/module_start_bad_ident.c3 b/test/test_suite2/module/module_start_bad_ident.c3 new file mode 100644 index 000000000..3502724ba --- /dev/null +++ b/test/test_suite2/module/module_start_bad_ident.c3 @@ -0,0 +1 @@ +module BIG::MONEY; // #error: The module name must consist of only lower case letters \ No newline at end of file diff --git a/test/test_suite2/module/module_start_invalid.c3 b/test/test_suite2/module/module_start_invalid.c3 new file mode 100644 index 000000000..1c8e68bb9 --- /dev/null +++ b/test/test_suite2/module/module_start_invalid.c3 @@ -0,0 +1 @@ +module &&; // #error: 'module' should be followed by a module name \ No newline at end of file diff --git a/test/test_suite2/module/module_start_keyword.c3 b/test/test_suite2/module/module_start_keyword.c3 new file mode 100644 index 000000000..84ff3d77c --- /dev/null +++ b/test/test_suite2/module/module_start_keyword.c3 @@ -0,0 +1 @@ +module if::hello; // #error: The module name cannot contain a reserved keyword \ No newline at end of file diff --git a/test/test_suite2/module/private_module.c3 b/test/test_suite2/module/private_module.c3 new file mode 100644 index 000000000..b29de1f17 --- /dev/null +++ b/test/test_suite2/module/private_module.c3 @@ -0,0 +1 @@ +module private foo; \ No newline at end of file diff --git a/test/test_suite2/module/unknown_modules.c3 b/test/test_suite2/module/unknown_modules.c3 new file mode 100644 index 000000000..a800c0fc8 --- /dev/null +++ b/test/test_suite2/module/unknown_modules.c3 @@ -0,0 +1,4 @@ +module test; + +import foo; // #error: No module named 'foo' could be found +import bar; // #error: No module named 'bar' could be found \ No newline at end of file diff --git a/test/test_suite2/pointers/array_pointer_decay.c3t b/test/test_suite2/pointers/array_pointer_decay.c3t new file mode 100644 index 000000000..16bced48f --- /dev/null +++ b/test/test_suite2/pointers/array_pointer_decay.c3t @@ -0,0 +1,78 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*, ...); + +fn void main() +{ + int[3] x; + int[3]* y = &x; + int* z = y; + int[] sub = y; + int y1 = y[1]; + int z1 = z[1]; + int* xx = &x + 1; + int[3]* yy = (int[3]*)(xx); + int* zz = yy - 1; + printf("%p = %p = %p, %p = %p\n", y, z, zz, &y[1], xx); + x[1] = 123; + printf("%d = %d\n", (&x)[1], y[1]); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca [3 x i32], align 4 + %y = alloca ptr, align 8 + %z = alloca ptr, align 8 + %sub = alloca %"int[]", align 8 + %y1 = alloca i32, align 4 + %z1 = alloca i32, align 4 + %xx = alloca ptr, align 8 + %yy = alloca ptr, align 8 + %zz = alloca ptr, align 8 + %0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 0 + store i32 0, ptr %0, align 4 + %1 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + store i32 0, ptr %1, align 4 + %2 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 2 + store i32 0, ptr %2, align 4 + store ptr %x, ptr %y, align 8 + %3 = load ptr, ptr %y, align 8 + store ptr %3, ptr %z, align 8 + %4 = load ptr, ptr %y, align 8 + %5 = insertvalue %"int[]" undef, ptr %4, 0 + %6 = insertvalue %"int[]" %5, i64 3, 1 + store %"int[]" %6, ptr %sub, align 8 + %7 = load ptr, ptr %y, align 8 + %8 = getelementptr inbounds [3 x i32], ptr %7, i64 0, i64 1 + %9 = load i32, ptr %8, align 4 + store i32 %9, ptr %y1, align 4 + %10 = load ptr, ptr %z, align 8 + %ptroffset = getelementptr inbounds i32, ptr %10, i64 1 + %11 = load i32, ptr %ptroffset, align 4 + store i32 %11, ptr %z1, align 4 + %ptroffset1 = getelementptr i32, ptr %x, i64 1 + store ptr %ptroffset1, ptr %xx, align 8 + %12 = load ptr, ptr %xx, align 8 + store ptr %12, ptr %yy, align 8 + %13 = load ptr, ptr %yy, align 8 + %ptroffset2 = getelementptr i32, ptr %13, i64 -1 + store ptr %ptroffset2, ptr %zz, align 8 + %14 = load ptr, ptr %y, align 8 + %15 = load ptr, ptr %z, align 8 + %16 = load ptr, ptr %zz, align 8 + %17 = load ptr, ptr %y, align 8 + %18 = getelementptr inbounds [3 x i32], ptr %17, i64 0, i64 1 + %19 = load ptr, ptr %xx, align 8 + call void (ptr, ...) @printf(ptr @.str, ptr %14, ptr %15, ptr %16, ptr %18, ptr %19) + %20 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + store i32 123, ptr %20, align 4 + %21 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + %22 = load i32, ptr %21, align 4 + %23 = load ptr, ptr %y, align 8 + %24 = getelementptr inbounds [3 x i32], ptr %23, i64 0, i64 1 + %25 = load i32, ptr %24, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %22, i32 %25) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/pointers/const_pointer.c3t b/test/test_suite2/pointers/const_pointer.c3t new file mode 100644 index 000000000..01c6da7a0 --- /dev/null +++ b/test/test_suite2/pointers/const_pointer.c3t @@ -0,0 +1,16 @@ +// #target: macos-x64 + +module const_pointer; + +private double foo = 17; +private double bar = 12.0; +private float xx = 12.0; + +private void*[3] data = { &foo, &bar, &xx }; + +/* #expect: const_pointer.ll + +@const_pointer.foo = protected global double 1.700000e+01, align 8 +@const_pointer.bar = protected global double 1.200000e+01, align 8 +@const_pointer.xx = protected global float 1.200000e+01, align 4 +@const_pointer.data = protected unnamed_addr global [3 x ptr] [ptr @const_pointer.foo, ptr @const_pointer.bar, ptr @const_pointer.xx], align 16 diff --git a/test/test_suite2/pointers/pointer_index.c3t b/test/test_suite2/pointers/pointer_index.c3t new file mode 100644 index 000000000..875c06ec2 --- /dev/null +++ b/test/test_suite2/pointers/pointer_index.c3t @@ -0,0 +1,78 @@ +module pointer_index; + +fn void test1(int* x) +{ + int a = x[0]; + int b = *x; + int c = x[1]; + int d = x[-1]; +} + +fn void test2(char* x) +{ + char a = x[0]; + char b = *x; + char c = x[1]; +} + +fn void test3(long* x) +{ + long a = x[0]; + long b = *x; + long c = x[1]; +} + +// #expect: pointer_index.ll + +define void @pointer_index.test1(ptr %0) #0 { +entry: + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %c = alloca i32, align 4 + %d = alloca i32, align 4 + %ptroffset = getelementptr inbounds i32, ptr %0, i64 0 + %1 = load i32, ptr %ptroffset, align 4 + store i32 %1, ptr %a, align 4 + %2 = load i32, ptr %0, align 8 + store i32 %2, ptr %b, align 4 + %ptroffset1 = getelementptr inbounds i32, ptr %0, i64 1 + %3 = load i32, ptr %ptroffset1, align 4 + store i32 %3, ptr %c, align 4 + %ptroffset2 = getelementptr inbounds i32, ptr %0, i64 -1 + %4 = load i32, ptr %ptroffset2, align 4 + store i32 %4, ptr %d, align 4 + ret void +} + +; Function Attrs: nounwind +define void @pointer_index.test2(ptr %0) #0 { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + %c = alloca i8, align 1 + %ptroffset = getelementptr inbounds i8, ptr %0, i64 0 + %1 = load i8, ptr %ptroffset, align 1 + store i8 %1, ptr %a, align 1 + %2 = load i8, ptr %0, align 8 + store i8 %2, ptr %b, align 1 + %ptroffset1 = getelementptr inbounds i8, ptr %0, i64 1 + %3 = load i8, ptr %ptroffset1, align 1 + store i8 %3, ptr %c, align 1 + ret void +} + +define void @pointer_index.test3(ptr %0) #0 { +entry: + %a = alloca i64, align 8 + %b = alloca i64, align 8 + %c = alloca i64, align 8 + %ptroffset = getelementptr inbounds i64, ptr %0, i64 0 + %1 = load i64, ptr %ptroffset, align 8 + store i64 %1, ptr %a, align 8 + %2 = load i64, ptr %0, align 8 + store i64 %2, ptr %b, align 8 + %ptroffset1 = getelementptr inbounds i64, ptr %0, i64 1 + %3 = load i64, ptr %ptroffset1, align 8 + store i64 %3, ptr %c, align 8 + ret void +} diff --git a/test/test_suite2/pointers/subarray_variant_to_ptr.c3t b/test/test_suite2/pointers/subarray_variant_to_ptr.c3t new file mode 100644 index 000000000..986a669e6 --- /dev/null +++ b/test/test_suite2/pointers/subarray_variant_to_ptr.c3t @@ -0,0 +1,96 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char*, ...); + +fn void test1(variant z) +{ + int* w = z.ptr; + printf("%d\n", *w); +} + +fn void test2(int[] z) +{ + int* w = z.ptr; + printf("%d\n", *w); +} + +fn void main() +{ + int x = 123; + int y = 293483; + int[2] w = { 144, 772 }; + test1(&x); + test2(w[..]); +} + +/* #expect: foo.ll + +%variant = type { ptr, i64 } +%"int[]" = type { ptr, i64 } + +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 + +define void @foo.test1(i64 %0, ptr %1) #0 { +entry: + %z = alloca %variant, align 8 + %w = alloca ptr, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %z, i32 0, i32 0 + store i64 %0, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %z, i32 0, i32 1 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds %variant, ptr %z, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + store ptr %5, ptr %w, align 8 + %6 = load ptr, ptr %w, align 8 + %7 = load i32, ptr %6, align 8 + call void (ptr, ...) @printf(ptr @.str, i32 %7) + ret void +} + +define void @foo.test2(ptr %0, i64 %1) #0 { +entry: + %z = alloca %"int[]", align 8 + %w = alloca ptr, align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %z, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %z, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + %4 = getelementptr inbounds %"int[]", ptr %z, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + store ptr %5, ptr %w, align 8 + %6 = load ptr, ptr %w, align 8 + %7 = load i32, ptr %6, align 8 + call void (ptr, ...) @printf(ptr @.str.1, i32 %7) + ret void +} + +define void @foo.main() #0 { +entry: + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %w = alloca [2 x i32], align 4 + %taddr = alloca %variant, align 8 + %taddr1 = alloca %"int[]", align 8 + store i32 123, ptr %x, align 4 + store i32 293483, ptr %y, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %w, ptr align 4 @.__const, i32 8, i1 false) + %0 = insertvalue %variant undef, ptr %x, 0 + %1 = insertvalue %variant %0, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %1, ptr %taddr, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %taddr, i32 0, i32 0 + %lo = load i64, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %taddr, i32 0, i32 1 + %hi = load ptr, ptr %3, align 8 + call void @foo.test1(i64 %lo, ptr %hi) + %4 = getelementptr inbounds [2 x i32], ptr %w, i64 0, i64 0 + %5 = insertvalue %"int[]" undef, ptr %4, 0 + %6 = insertvalue %"int[]" %5, i64 2, 1 + store %"int[]" %6, ptr %taddr1, align 8 + %7 = getelementptr inbounds { ptr, i64 }, ptr %taddr1, i32 0, i32 0 + %lo2 = load ptr, ptr %7, align 8 + %8 = getelementptr inbounds { ptr, i64 }, ptr %taddr1, i32 0, i32 1 + %hi3 = load i64, ptr %8, align 8 + call void @foo.test2(ptr %lo2, i64 %hi3) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/precedence/required_parens.c3 b/test/test_suite2/precedence/required_parens.c3 new file mode 100644 index 000000000..176469480 --- /dev/null +++ b/test/test_suite2/precedence/required_parens.c3 @@ -0,0 +1,13 @@ +module foo; +import std::io; + +fn void main() +{ + int i = 0; + int j = i ^ i | i; // #error: You need to add explicit parentheses to clarify precedence. + bool x = i == j == i; // #error: You need to add explicit parentheses to clarify precedence. + int k = i >> j << k; // #error: You need to add explicit parentheses to clarify precedence. + bool xk = i && j || i; + int y = i + j + i; + int yy = i * i / i + i - i; +} \ No newline at end of file diff --git a/test/test_suite2/regression/crash_on_right_paren_macro.c3 b/test/test_suite2/regression/crash_on_right_paren_macro.c3 new file mode 100644 index 000000000..9605bf231 --- /dev/null +++ b/test/test_suite2/regression/crash_on_right_paren_macro.c3 @@ -0,0 +1,6 @@ +macro void hello($b$Bar x; // #error: Expected ')' + @hello(1); + var $foo = 1; + $foo; + FOO; +} diff --git a/test/test_suite2/safe/deref.c3t b/test/test_suite2/safe/deref.c3t new file mode 100644 index 000000000..8f13e8c9e --- /dev/null +++ b/test/test_suite2/safe/deref.c3t @@ -0,0 +1,30 @@ +// #safe: yes +module foo; + +fn void main() +{ + int* x; + int y = *x; +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca ptr, align 8 + %y = alloca i32, align 4 + store ptr null, ptr %x, align 8 + %0 = load ptr, ptr %x, align 8 + %checknull = icmp eq ptr %0, null + br i1 %checknull, label %panic, label %checkok + +panic: ; preds = %entry + call void @"std::core::builtin.panic"(ptr @.zstr, ptr @.zstr.1, ptr @.zstr.2, i32 6) + br label %checkok + +checkok: ; preds = %panic, %entry + %1 = load i32, ptr %0, align 8 + store i32 %1, ptr %y, align 4 + ret void +} + diff --git a/test/test_suite2/slices/slice_assign.c3t b/test/test_suite2/slices/slice_assign.c3t new file mode 100644 index 000000000..913087c15 --- /dev/null +++ b/test/test_suite2/slices/slice_assign.c3t @@ -0,0 +1,90 @@ +// #target: macos-x64 +module test; + +extern fn void printf(char*, ...); + +fn void main() +{ + int[8] x; + x[0..1] = 3; + x[1..2] = 5; + x[5..7] = 52; + foreach (i : x) + { + printf("%d\n", i); + } + x[0..7] = 123; +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 + +; Function Attrs: nounwind +declare void @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %x = alloca [8 x i32], align 16 + %anon = alloca i64, align 8 + %i = alloca i32, align 4 + call void @llvm.memset.p0.i64(ptr align 16 %x, i8 0, i64 32, i1 false) + %0 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 0 + store i32 3, ptr %0, align 4 + %1 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 1 + store i32 3, ptr %1, align 4 + %2 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 1 + store i32 5, ptr %2, align 4 + %3 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 2 + store i32 5, ptr %3, align 4 + %4 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 5 + store i32 52, ptr %4, align 4 + %5 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 6 + store i32 52, ptr %5, align 4 + %6 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 7 + store i32 52, ptr %6, align 4 + store i64 0, ptr %anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %7 = load i64, ptr %anon, align 8 + %gt = icmp ugt i64 8, %7 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %8 = load i64, ptr %anon, align 8 + %9 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 %8 + %10 = load i32, ptr %9, align 4 + store i32 %10, ptr %i, align 4 + %11 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %11) + %12 = load i64, ptr %anon, align 8 + %add = add i64 %12, 1 + store i64 %add, ptr %anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + br label %cond + +cond: ; preds = %assign, %loop.exit + %13 = phi i64 [ 0, %loop.exit ], [ %add1, %assign ] + %le = icmp sle i64 %13, 7 + br i1 %le, label %assign, label %exit + +assign: ; preds = %cond + %14 = getelementptr inbounds [8 x i32], ptr %x, i64 0, i64 %13 + store i32 123, ptr %14, align 4 + %add1 = add i64 %13, 1 + br label %cond + +exit: ; preds = %cond + ret void +} + +; Function Attrs: nounwind +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} diff --git a/test/test_suite2/statements/binary_fail.c3 b/test/test_suite2/statements/binary_fail.c3 new file mode 100644 index 000000000..cb243ba8b --- /dev/null +++ b/test/test_suite2/statements/binary_fail.c3 @@ -0,0 +1,9 @@ +fn void test() +{ + float a; + float b; + int *c; + int *d; + if ((a + c) // #error: A value of type 'float' cannot be added to 'int*', an integer was expected here + + (b + d)) return; // #error: A value of type 'float' cannot be added to 'int*', an integer was expected here +} \ No newline at end of file diff --git a/test/test_suite2/statements/call_missing_paren.c3 b/test/test_suite2/statements/call_missing_paren.c3 new file mode 100644 index 000000000..3bcb40748 --- /dev/null +++ b/test/test_suite2/statements/call_missing_paren.c3 @@ -0,0 +1,7 @@ +fn void foo(int a) {} + +fn int main() +{ + foo(10, foo(); // #error: Did you forget a ')' before this + return 0; +} \ No newline at end of file diff --git a/test/test_suite2/statements/comparison_widening.c3t b/test/test_suite2/statements/comparison_widening.c3t new file mode 100644 index 000000000..207c71a12 --- /dev/null +++ b/test/test_suite2/statements/comparison_widening.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 + +fn void test1() +{ + char a = 1; + int b = 2; + char c = b > a ? 1u8 : 0u8; + int d = b ?: 1; +} + +// #expect: comparison_widening.ll + +define void @comparison_widening.test1() #0 { +entry: + %a = alloca i8, align 1 + %b = alloca i32, align 4 + %c = alloca i8, align 1 + %d = alloca i32, align 4 + store i8 1, ptr %a, align 1 + store i32 2, ptr %b, align 4 + %0 = load i32, ptr %b, align 4 + %1 = load i8, ptr %a, align 1 + %uiuiext = zext i8 %1 to i32 + %gt = icmp sgt i32 %0, %uiuiext + %check = icmp sge i32 %uiuiext, 0 + %siui-gt = and i1 %check, %gt + %ternary = select i1 %siui-gt, i8 1, i8 0 + store i8 %ternary, ptr %c, align 1 + %2 = load i32, ptr %b, align 4 + %intbool = icmp ne i32 %2, 0 + %elvis = select i1 %intbool, i32 %2, i32 1 + store i32 %elvis, ptr %d, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/statements/conditional_return.c3 b/test/test_suite2/statements/conditional_return.c3 new file mode 100644 index 000000000..1337d5c26 --- /dev/null +++ b/test/test_suite2/statements/conditional_return.c3 @@ -0,0 +1,12 @@ +fn int testReturnWithConditional() +{ + int i = 0; + if (i > 0) + { + return 1; + } + else + { + return 2; + } +} \ No newline at end of file diff --git a/test/test_suite2/statements/custom_foreach_with_ref.c3t b/test/test_suite2/statements/custom_foreach_with_ref.c3t new file mode 100644 index 000000000..c180a5f58 --- /dev/null +++ b/test/test_suite2/statements/custom_foreach_with_ref.c3t @@ -0,0 +1,480 @@ +// #target: macos-x64 +module foo; + +struct Foo +{ + int[3] a; +} + +extern fn void printf(char*, ...); + +macro int* Foo.@operator_element_at_ref(Foo &f, int a) @operator(elementref) +{ + return &f.a[a]; +} + +macro int Foo.@operator_len(Foo &f) @operator(len) +{ + return 3; +} + +macro int Foo.@operator_element_at(Foo &f, int a) @operator(elementat) +{ + return f.a[a]; +} + +fn int[5] getFields() +{ + printf("getFields\n"); + return int[5] { 3, 5, 2, 10, 111}; +} +fn Foo *call(Foo *f) +{ + printf("Call made\n"); + return f; +} +fn void main() +{ + Foo x = { { 1, 5, 7} }; + printf("%d %d %d\n", x[0], x[1], x[2]); + foreach (i, int y : *call(&x)) + { + printf("Hello %d: %d\n", i, y); + } + foreach (i, int* &y : x) + { + *y += 1; + printf("Hello %d: %d\n", i, *y); + } + foreach (i, int y : x) + { + printf("After one %d: %d\n", i, y); + } + + foreach (i, int y : &x) + { + printf("By pointer %d: %d\n", i, y); + } + + foreach (i, int y : x) + { + printf("Adding %d: %d\n", i, y); + i++; + } + + foreach(i, y : int[5] { 1, 2, 10, 111, 123 } ) + { + printf("Adding %d: %d\n", i, y); + i++; + } + foreach(i, y : getFields() ) + { + printf("Pull value %d: %d\n", i, y); + } + foreach(i, y : &&getFields()) + { + printf("Pull value tempptr %d: %d\n", i, y); + } + printf("%d %d\n", x[0], x[1]); + int* y = &x[1]; + *y += 1; + printf("%d %d\n", x[0], x[1]); +} + +/* #expect: foo.ll + + +%Foo = type { [3 x i32] } + +@.typeid.foo.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8 +@.str = private unnamed_addr constant [11 x i8] c"getFields\0A\00", align 1 +@.str.1 = private unnamed_addr constant [11 x i8] c"Call made\0A\00", align 1 +@.__const = private unnamed_addr constant %Foo { [3 x i32] [i32 1, i32 5, i32 7] }, align 4 +@.str.2 = private unnamed_addr constant [10 x i8] c"%d %d %d\0A\00", align 1 +@.str.3 = private unnamed_addr constant [14 x i8] c"Hello %d: %d\0A\00", align 1 +@.str.4 = private unnamed_addr constant [14 x i8] c"Hello %d: %d\0A\00", align 1 +@.str.5 = private unnamed_addr constant [18 x i8] c"After one %d: %d\0A\00", align 1 +@.str.6 = private unnamed_addr constant [19 x i8] c"By pointer %d: %d\0A\00", align 1 +@.str.7 = private unnamed_addr constant [15 x i8] c"Adding %d: %d\0A\00", align 1 +@.__const.8 = private unnamed_addr constant [5 x i32] [i32 1, i32 2, i32 10, i32 111, i32 123], align 16 +@.str.9 = private unnamed_addr constant [15 x i8] c"Adding %d: %d\0A\00", align 1 +@.str.10 = private unnamed_addr constant [19 x i8] c"Pull value %d: %d\0A\00", align 1 +@.str.11 = private unnamed_addr constant [27 x i8] c"Pull value tempptr %d: %d\0A\00", align 1 +@.str.12 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 +@.str.13 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 + +define void @foo.getFields(ptr noalias sret([5 x i32]) align 4 %0) #0 { +entry: + %literal = alloca [5 x i32], align 16 + call void (ptr, ...) @printf(ptr @.str) + %1 = getelementptr inbounds [5 x i32], ptr %literal, i64 0, i64 0 + store i32 3, ptr %1, align 4 + %2 = getelementptr inbounds [5 x i32], ptr %literal, i64 0, i64 1 + store i32 5, ptr %2, align 4 + %3 = getelementptr inbounds [5 x i32], ptr %literal, i64 0, i64 2 + store i32 2, ptr %3, align 4 + %4 = getelementptr inbounds [5 x i32], ptr %literal, i64 0, i64 3 + store i32 10, ptr %4, align 4 + %5 = getelementptr inbounds [5 x i32], ptr %literal, i64 0, i64 4 + store i32 111, ptr %5, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 20, i1 false) + ret void +} + +define ptr @foo.call(ptr %0) #0 { +entry: + call void (ptr, ...) @printf(ptr @.str.1) + ret ptr %0 +} + +define void @foo.main() #0 { +entry: + %x = alloca %Foo, align 4 + %a = alloca i32, align 4 + %a1 = alloca i32, align 4 + %a3 = alloca i32, align 4 + %anon = alloca i32, align 4 + %anon5 = alloca ptr, align 8 + %anon6 = alloca i32, align 4 + %i = alloca i32, align 4 + %y = alloca i32, align 4 + %a7 = alloca i32, align 4 + %anon9 = alloca i32, align 4 + %anon10 = alloca i32, align 4 + %i14 = alloca i32, align 4 + %y15 = alloca ptr, align 8 + %a16 = alloca i32, align 4 + %anon21 = alloca i32, align 4 + %anon22 = alloca i32, align 4 + %i26 = alloca i32, align 4 + %y27 = alloca i32, align 4 + %a28 = alloca i32, align 4 + %anon32 = alloca i32, align 4 + %anon33 = alloca i32, align 4 + %i37 = alloca i32, align 4 + %y38 = alloca i32, align 4 + %a39 = alloca i32, align 4 + %anon43 = alloca i32, align 4 + %anon44 = alloca i32, align 4 + %i48 = alloca i32, align 4 + %y49 = alloca i32, align 4 + %a50 = alloca i32, align 4 + %anon55 = alloca i64, align 8 + %anon56 = alloca [5 x i32], align 16 + %i59 = alloca i64, align 8 + %y60 = alloca i32, align 4 + %anon64 = alloca i64, align 8 + %anon65 = alloca [5 x i32], align 16 + %sretparam = alloca [5 x i32], align 4 + %i69 = alloca i64, align 8 + %y70 = alloca i32, align 4 + %anon73 = alloca i64, align 8 + %anon74 = alloca ptr, align 8 + %sretparam75 = alloca [5 x i32], align 4 + %i79 = alloca i64, align 8 + %y80 = alloca i32, align 4 + %a83 = alloca i32, align 4 + %a85 = alloca i32, align 4 + %y87 = alloca ptr, align 8 + %a88 = alloca i32, align 4 + %a91 = alloca i32, align 4 + %a93 = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + store i32 0, ptr %a, align 4 + %0 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %1 = load i32, ptr %a, align 4 + %sisiext = sext i32 %1 to i64 + %2 = getelementptr inbounds [3 x i32], ptr %0, i64 0, i64 %sisiext + %3 = load i32, ptr %2, align 4 + store i32 1, ptr %a1, align 4 + %4 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %5 = load i32, ptr %a1, align 4 + %sisiext2 = sext i32 %5 to i64 + %6 = getelementptr inbounds [3 x i32], ptr %4, i64 0, i64 %sisiext2 + %7 = load i32, ptr %6, align 4 + store i32 2, ptr %a3, align 4 + %8 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %9 = load i32, ptr %a3, align 4 + %sisiext4 = sext i32 %9 to i64 + %10 = getelementptr inbounds [3 x i32], ptr %8, i64 0, i64 %sisiext4 + %11 = load i32, ptr %10, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %3, i32 %7, i32 %11) + store i32 0, ptr %anon, align 4 + %12 = call ptr @foo.call(ptr %x) + store ptr %12, ptr %anon5, align 8 + store i32 3, ptr %anon6, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %13 = load i32, ptr %anon, align 4 + %14 = load i32, ptr %anon6, align 4 + %lt = icmp slt i32 %13, %14 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %15 = load i32, ptr %anon, align 4 + store i32 %15, ptr %i, align 4 + %16 = load ptr, ptr %anon5, align 8 + %17 = load i32, ptr %anon, align 4 + store i32 %17, ptr %a7, align 4 + %18 = getelementptr inbounds %Foo, ptr %16, i32 0, i32 0 + %19 = load i32, ptr %a7, align 4 + %sisiext8 = sext i32 %19 to i64 + %20 = getelementptr inbounds [3 x i32], ptr %18, i64 0, i64 %sisiext8 + %21 = load i32, ptr %20, align 4 + store i32 %21, ptr %y, align 4 + %22 = load i32, ptr %i, align 4 + %23 = load i32, ptr %y, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %22, i32 %23) + %24 = load i32, ptr %anon, align 4 + %add = add i32 %24, 1 + store i32 %add, ptr %anon, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + store i32 0, ptr %anon9, align 4 + store i32 3, ptr %anon10, align 4 + br label %loop.cond11 + +loop.cond11: ; preds = %loop.body13, %loop.exit + %25 = load i32, ptr %anon9, align 4 + %26 = load i32, ptr %anon10, align 4 + %lt12 = icmp slt i32 %25, %26 + br i1 %lt12, label %loop.body13, label %loop.exit20 + +loop.body13: ; preds = %loop.cond11 + %27 = load i32, ptr %anon9, align 4 + store i32 %27, ptr %i14, align 4 + %28 = load i32, ptr %anon9, align 4 + store i32 %28, ptr %a16, align 4 + %29 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %30 = load i32, ptr %a16, align 4 + %sisiext17 = sext i32 %30 to i64 + %31 = getelementptr inbounds [3 x i32], ptr %29, i64 0, i64 %sisiext17 + store ptr %31, ptr %y15, align 8 + %32 = load ptr, ptr %y15, align 8 + %33 = load i32, ptr %32, align 8 + %add18 = add i32 %33, 1 + store i32 %add18, ptr %32, align 8 + %34 = load i32, ptr %i14, align 4 + %35 = load ptr, ptr %y15, align 8 + %36 = load i32, ptr %35, align 8 + call void (ptr, ...) @printf(ptr @.str.4, i32 %34, i32 %36) + %37 = load i32, ptr %anon9, align 4 + %add19 = add i32 %37, 1 + store i32 %add19, ptr %anon9, align 4 + br label %loop.cond11 + +loop.exit20: ; preds = %loop.cond11 + store i32 0, ptr %anon21, align 4 + store i32 3, ptr %anon22, align 4 + br label %loop.cond23 + +loop.cond23: ; preds = %loop.body25, %loop.exit20 + %38 = load i32, ptr %anon21, align 4 + %39 = load i32, ptr %anon22, align 4 + %lt24 = icmp slt i32 %38, %39 + br i1 %lt24, label %loop.body25, label %loop.exit31 + +loop.body25: ; preds = %loop.cond23 + %40 = load i32, ptr %anon21, align 4 + store i32 %40, ptr %i26, align 4 + %41 = load i32, ptr %anon21, align 4 + store i32 %41, ptr %a28, align 4 + %42 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %43 = load i32, ptr %a28, align 4 + %sisiext29 = sext i32 %43 to i64 + %44 = getelementptr inbounds [3 x i32], ptr %42, i64 0, i64 %sisiext29 + %45 = load i32, ptr %44, align 4 + store i32 %45, ptr %y27, align 4 + %46 = load i32, ptr %i26, align 4 + %47 = load i32, ptr %y27, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %46, i32 %47) + %48 = load i32, ptr %anon21, align 4 + %add30 = add i32 %48, 1 + store i32 %add30, ptr %anon21, align 4 + br label %loop.cond23 + +loop.exit31: ; preds = %loop.cond23 + store i32 0, ptr %anon32, align 4 + store i32 3, ptr %anon33, align 4 + br label %loop.cond34 + +loop.cond34: ; preds = %loop.body36, %loop.exit31 + %49 = load i32, ptr %anon32, align 4 + %50 = load i32, ptr %anon33, align 4 + %lt35 = icmp slt i32 %49, %50 + br i1 %lt35, label %loop.body36, label %loop.exit42 + +loop.body36: ; preds = %loop.cond34 + %51 = load i32, ptr %anon32, align 4 + store i32 %51, ptr %i37, align 4 + %52 = load i32, ptr %anon32, align 4 + store i32 %52, ptr %a39, align 4 + %53 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %54 = load i32, ptr %a39, align 4 + %sisiext40 = sext i32 %54 to i64 + %55 = getelementptr inbounds [3 x i32], ptr %53, i64 0, i64 %sisiext40 + %56 = load i32, ptr %55, align 4 + store i32 %56, ptr %y38, align 4 + %57 = load i32, ptr %i37, align 4 + %58 = load i32, ptr %y38, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %57, i32 %58) + %59 = load i32, ptr %anon32, align 4 + %add41 = add i32 %59, 1 + store i32 %add41, ptr %anon32, align 4 + br label %loop.cond34 + +loop.exit42: ; preds = %loop.cond34 + store i32 0, ptr %anon43, align 4 + store i32 3, ptr %anon44, align 4 + br label %loop.cond45 + +loop.cond45: ; preds = %loop.body47, %loop.exit42 + %60 = load i32, ptr %anon43, align 4 + %61 = load i32, ptr %anon44, align 4 + %lt46 = icmp slt i32 %60, %61 + br i1 %lt46, label %loop.body47, label %loop.exit54 + +loop.body47: ; preds = %loop.cond45 + %62 = load i32, ptr %anon43, align 4 + store i32 %62, ptr %i48, align 4 + %63 = load i32, ptr %anon43, align 4 + store i32 %63, ptr %a50, align 4 + %64 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %65 = load i32, ptr %a50, align 4 + %sisiext51 = sext i32 %65 to i64 + %66 = getelementptr inbounds [3 x i32], ptr %64, i64 0, i64 %sisiext51 + %67 = load i32, ptr %66, align 4 + store i32 %67, ptr %y49, align 4 + %68 = load i32, ptr %i48, align 4 + %69 = load i32, ptr %y49, align 4 + call void (ptr, ...) @printf(ptr @.str.7, i32 %68, i32 %69) + %70 = load i32, ptr %i48, align 4 + %add52 = add i32 %70, 1 + store i32 %add52, ptr %i48, align 4 + %71 = load i32, ptr %anon43, align 4 + %add53 = add i32 %71, 1 + store i32 %add53, ptr %anon43, align 4 + br label %loop.cond45 + +loop.exit54: ; preds = %loop.cond45 + store i64 0, ptr %anon55, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %anon56, ptr align 16 @.__const.8, i32 20, i1 false) + br label %loop.cond57 + +loop.cond57: ; preds = %loop.body58, %loop.exit54 + %72 = load i64, ptr %anon55, align 8 + %gt = icmp ugt i64 5, %72 + br i1 %gt, label %loop.body58, label %loop.exit63 + +loop.body58: ; preds = %loop.cond57 + %73 = load i64, ptr %anon55, align 8 + store i64 %73, ptr %i59, align 8 + %74 = load i64, ptr %anon55, align 8 + %75 = getelementptr inbounds [5 x i32], ptr %anon56, i64 0, i64 %74 + %76 = load i32, ptr %75, align 4 + store i32 %76, ptr %y60, align 4 + %77 = load i64, ptr %i59, align 8 + %78 = load i32, ptr %y60, align 4 + call void (ptr, ...) @printf(ptr @.str.9, i64 %77, i32 %78) + %79 = load i64, ptr %i59, align 8 + %add61 = add i64 %79, 1 + store i64 %add61, ptr %i59, align 8 + %80 = load i64, ptr %anon55, align 8 + %add62 = add i64 %80, 1 + store i64 %add62, ptr %anon55, align 8 + br label %loop.cond57 + +loop.exit63: ; preds = %loop.cond57 + store i64 0, ptr %anon64, align 8 + call void @foo.getFields(ptr sret([5 x i32]) align 4 %sretparam) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %anon65, ptr align 4 %sretparam, i32 20, i1 false) + br label %loop.cond66 + +loop.cond66: ; preds = %loop.body68, %loop.exit63 + %81 = load i64, ptr %anon64, align 8 + %gt67 = icmp ugt i64 5, %81 + br i1 %gt67, label %loop.body68, label %loop.exit72 + +loop.body68: ; preds = %loop.cond66 + %82 = load i64, ptr %anon64, align 8 + store i64 %82, ptr %i69, align 8 + %83 = load i64, ptr %anon64, align 8 + %84 = getelementptr inbounds [5 x i32], ptr %anon65, i64 0, i64 %83 + %85 = load i32, ptr %84, align 4 + store i32 %85, ptr %y70, align 4 + %86 = load i64, ptr %i69, align 8 + %87 = load i32, ptr %y70, align 4 + call void (ptr, ...) @printf(ptr @.str.10, i64 %86, i32 %87) + %88 = load i64, ptr %anon64, align 8 + %add71 = add i64 %88, 1 + store i64 %add71, ptr %anon64, align 8 + br label %loop.cond66 + +loop.exit72: ; preds = %loop.cond66 + store i64 0, ptr %anon73, align 8 + call void @foo.getFields(ptr sret([5 x i32]) align 4 %sretparam75) + store ptr %sretparam75, ptr %anon74, align 8 + br label %loop.cond76 + +loop.cond76: ; preds = %loop.body78, %loop.exit72 + %89 = load i64, ptr %anon73, align 8 + %gt77 = icmp ugt i64 5, %89 + br i1 %gt77, label %loop.body78, label %loop.exit82 + +loop.body78: ; preds = %loop.cond76 + %90 = load i64, ptr %anon73, align 8 + store i64 %90, ptr %i79, align 8 + %91 = load ptr, ptr %anon74, align 8 + %92 = load i64, ptr %anon73, align 8 + %93 = getelementptr inbounds [5 x i32], ptr %91, i64 0, i64 %92 + %94 = load i32, ptr %93, align 4 + store i32 %94, ptr %y80, align 4 + %95 = load i64, ptr %i79, align 8 + %96 = load i32, ptr %y80, align 4 + call void (ptr, ...) @printf(ptr @.str.11, i64 %95, i32 %96) + %97 = load i64, ptr %anon73, align 8 + %add81 = add i64 %97, 1 + store i64 %add81, ptr %anon73, align 8 + br label %loop.cond76 + +loop.exit82: ; preds = %loop.cond76 + store i32 0, ptr %a83, align 4 + %98 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %99 = load i32, ptr %a83, align 4 + %sisiext84 = sext i32 %99 to i64 + %100 = getelementptr inbounds [3 x i32], ptr %98, i64 0, i64 %sisiext84 + %101 = load i32, ptr %100, align 4 + store i32 1, ptr %a85, align 4 + %102 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %103 = load i32, ptr %a85, align 4 + %sisiext86 = sext i32 %103 to i64 + %104 = getelementptr inbounds [3 x i32], ptr %102, i64 0, i64 %sisiext86 + %105 = load i32, ptr %104, align 4 + call void (ptr, ...) @printf(ptr @.str.12, i32 %101, i32 %105) + store i32 1, ptr %a88, align 4 + %106 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %107 = load i32, ptr %a88, align 4 + %sisiext89 = sext i32 %107 to i64 + %108 = getelementptr inbounds [3 x i32], ptr %106, i64 0, i64 %sisiext89 + store ptr %108, ptr %y87, align 8 + %109 = load ptr, ptr %y87, align 8 + %110 = load i32, ptr %109, align 8 + %add90 = add i32 %110, 1 + store i32 %add90, ptr %109, align 8 + store i32 0, ptr %a91, align 4 + %111 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %112 = load i32, ptr %a91, align 4 + %sisiext92 = sext i32 %112 to i64 + %113 = getelementptr inbounds [3 x i32], ptr %111, i64 0, i64 %sisiext92 + %114 = load i32, ptr %113, align 4 + store i32 1, ptr %a93, align 4 + %115 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %116 = load i32, ptr %a93, align 4 + %sisiext94 = sext i32 %116 to i64 + %117 = getelementptr inbounds [3 x i32], ptr %115, i64 0, i64 %sisiext94 + %118 = load i32, ptr %117, align 4 + call void (ptr, ...) @printf(ptr @.str.13, i32 %114, i32 %118) + ret void +} diff --git a/test/test_suite2/statements/default_args.c3 b/test/test_suite2/statements/default_args.c3 new file mode 100644 index 000000000..86005a917 --- /dev/null +++ b/test/test_suite2/statements/default_args.c3 @@ -0,0 +1,2 @@ + +define Foo = fn void(int a = 10); // #error: Function types may not have default arguments. diff --git a/test/test_suite2/statements/defer_break.c3t b/test/test_suite2/statements/defer_break.c3t new file mode 100644 index 000000000..c20d7f7ac --- /dev/null +++ b/test/test_suite2/statements/defer_break.c3t @@ -0,0 +1,114 @@ +module foo; + +extern fn void printf(char* message, ...); + +fn void defer1() {} +fn void defer2() {} +fn void defer3() {} +fn void defer4() {} +fn void defer5() {} +fn void defer6() {} +fn void defer7() {} +fn void defer8() {} +fn void defer9() {} +fn void defer10() {} +fn void defer11() {} + +fn int main(int argc, char** argv) +{ + int a = 0; + { + defer do { + if (a == 1) break; + defer1(); + } while(0); + defer2(); + } + defer defer3(); + while (a) + { + defer defer4(); + if (argc == 1) break; + defer defer5(); + defer6(); + } + defer defer7(); + while (a) + { + defer defer8(); + if (argc == 1) break; + defer defer9(); + defer10(); + break; + defer11(); + } + return 0; +} + +/* #expect: foo.ll + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + %a = alloca i32, align 4 + store i32 0, ptr %a, align 4 + call void @foo.defer2() + %2 = load i32, ptr %a, align 4 + %eq = icmp eq i32 %2, 1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + br label %loop.exit + +if.exit: ; preds = %entry + call void @foo.defer1() + br label %loop.exit + +loop.exit: ; preds = %if.exit, %if.then + br label %loop.cond + +loop.cond: ; preds = %if.exit3, %loop.exit + %3 = load i32, ptr %a, align 4 + %intbool = icmp ne i32 %3, 0 + br i1 %intbool, label %loop.body, label %loop.exit4 + +loop.body: ; preds = %loop.cond + %eq1 = icmp eq i32 %0, 1 + br i1 %eq1, label %if.then2, label %if.exit3 + +if.then2: ; preds = %loop.body + call void @foo.defer4() + br label %loop.exit4 + +if.exit3: ; preds = %loop.body + call void @foo.defer6() + call void @foo.defer5() + call void @foo.defer4() + br label %loop.cond + +loop.exit4: ; preds = %if.then2, %loop.cond + br label %loop.cond5 + +loop.cond5: ; preds = %loop.exit4 + %4 = load i32, ptr %a, align 4 + %intbool6 = icmp ne i32 %4, 0 + br i1 %intbool6, label %loop.body7, label %loop.exit11 + +loop.body7: ; preds = %loop.cond5 + %eq8 = icmp eq i32 %0, 1 + br i1 %eq8, label %if.then9, label %if.exit10 + +if.then9: ; preds = %loop.body7 + call void @foo.defer8() + br label %loop.exit11 + +if.exit10: ; preds = %loop.body7 + call void @foo.defer10() + call void @foo.defer9() + call void @foo.defer8() + br label %loop.exit11 + +loop.exit11: ; preds = %if.exit10, %if.then9, %loop.cond5 + call void @foo.defer7() + call void @foo.defer3() + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite2/statements/defer_break_simple.c3t b/test/test_suite2/statements/defer_break_simple.c3t new file mode 100644 index 000000000..d87e809a4 --- /dev/null +++ b/test/test_suite2/statements/defer_break_simple.c3t @@ -0,0 +1,58 @@ +// #target: macos-x64 +module test; + +fn void test2() {} +fn void testA() {} +fn void testB() {} +fn void test3() {} + +fn int main(int argc, char** argv) +{ + int a = 0; + while (a) + { + defer test2(); + defer + { + testA(); + testB(); + } + if (argc == 1) break; + test3(); + } + return 0; +} + +/* #expect: test.ll + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + %a = alloca i32, align 4 + store i32 0, ptr %a, align 4 + br label %loop.cond + +loop.cond: ; preds = %if.exit, %entry + %2 = load i32, ptr %a, align 4 + %intbool = icmp ne i32 %2, 0 + br i1 %intbool, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %eq = icmp eq i32 %0, 1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + call void @test.testA() + call void @test.testB() + call void @test.test2() + br label %loop.exit + +if.exit: ; preds = %loop.body + call void @test.test3() + call void @test.testA() + call void @test.testB() + call void @test.test2() + br label %loop.cond + +loop.exit: ; preds = %if.then, %loop.cond + ret i32 0 +} diff --git a/test/test_suite2/statements/defer_break_switch.c3t b/test/test_suite2/statements/defer_break_switch.c3t new file mode 100644 index 000000000..abec39467 --- /dev/null +++ b/test/test_suite2/statements/defer_break_switch.c3t @@ -0,0 +1,59 @@ + +fn void test1() +{} + +fn void test2() +{} + +fn void test(int i) +{ + bool b = true; + switch (i) + { + case 1: + defer test2(); + if (b) break; + test1(); + case 2: + test1(); + } +} + +/* #expect: defer_break_switch.ll + +define void @defer_break_switch.test(i32 %0) #0 { +entry: + %b = alloca i8, align 1 + %switch = alloca i32, align 4 + store i8 1, ptr %b, align 1 + store i32 %0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %1 = load i32, ptr %switch, align 4 + switch i32 %1, label %switch.exit [ + i32 1, label %switch.case + i32 2, label %switch.case1 + ] + +switch.case: ; preds = %switch.entry + %2 = load i8, ptr %b, align 1 + %3 = trunc i8 %2 to i1 + br i1 %3, label %if.then, label %if.exit + +if.then: ; preds = %switch.case + call void @defer_break_switch.test2() + br label %switch.exit + +if.exit: ; preds = %switch.case + call void @defer_break_switch.test1() + call void @defer_break_switch.test2() + br label %switch.exit + +switch.case1: ; preds = %switch.entry + call void @defer_break_switch.test1() + br label %switch.exit + +switch.exit: ; preds = %switch.case1, %if.exit, %if.then, %switch.entry + ret void +} diff --git a/test/test_suite2/statements/defer_do_while.c3t b/test/test_suite2/statements/defer_do_while.c3t new file mode 100644 index 000000000..d401502c8 --- /dev/null +++ b/test/test_suite2/statements/defer_do_while.c3t @@ -0,0 +1,38 @@ +// #target: macos-x64 +module foo; + +fn void test() +{ + int a; + do + { + a++; + defer a++; + } while(a < 10); +} + +/* #expect: foo.ll + +define void @foo.test() #0 { +entry: + %a = alloca i32, align 4 + store i32 0, ptr %a, align 4 + br label %loop.body + +loop.cond: ; preds = %loop.body + %0 = load i32, ptr %a, align 4 + %lt = icmp slt i32 %0, 10 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond, %entry + %1 = load i32, ptr %a, align 4 + %add = add i32 %1, 1 + store i32 %add, ptr %a, align 4 + %2 = load i32, ptr %a, align 4 + %add1 = add i32 %2, 1 + store i32 %add1, ptr %a, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} \ No newline at end of file diff --git a/test/test_suite2/statements/defer_in_block.c3t b/test/test_suite2/statements/defer_in_block.c3t new file mode 100644 index 000000000..46b3c9954 --- /dev/null +++ b/test/test_suite2/statements/defer_in_block.c3t @@ -0,0 +1,87 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*,...); + +fn void test(int x) +{ + defer printf("---\n"); + {| + defer printf("Hello %d\n", x); + x *= 2; + if (x < 100) return; + x *= 10000; + |}; + printf("+++\n"); + if (x == 0) + { + printf("0x\n"); + return; + } + if (x == 1) return; +} + +fn void main() +{ + test(123); + test(1); + test(0); +} +/* #expect: foo.ll + +define void @foo.test(i32 %0) #0 { +entry: + %x = alloca i32, align 4 + store i32 %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %mul = mul i32 %1, 2 + store i32 %mul, ptr %x, align 4 + %2 = load i32, ptr %x, align 4 + %lt = icmp slt i32 %2, 100 + br i1 %lt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %3 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %3) + br label %expr_block.exit + +if.exit: ; preds = %entry + %4 = load i32, ptr %x, align 4 + %mul1 = mul i32 %4, 10000 + store i32 %mul1, ptr %x, align 4 + %5 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %5) + br label %expr_block.exit + +expr_block.exit: ; preds = %if.exit, %if.then + call void (ptr, ...) @printf(ptr @.str.2) + %6 = load i32, ptr %x, align 4 + %eq = icmp eq i32 %6, 0 + br i1 %eq, label %if.then2, label %if.exit3 + +if.then2: ; preds = %expr_block.exit + call void (ptr, ...) @printf(ptr @.str.3) + call void (ptr, ...) @printf(ptr @.str.4) + ret void + +if.exit3: ; preds = %expr_block.exit + %7 = load i32, ptr %x, align 4 + %eq4 = icmp eq i32 %7, 1 + br i1 %eq4, label %if.then5, label %if.exit6 + +if.then5: ; preds = %if.exit3 + call void (ptr, ...) @printf(ptr @.str.5) + ret void + +if.exit6: ; preds = %if.exit3 + call void (ptr, ...) @printf(ptr @.str.6) + ret void +} + +; Function Attrs: nounwind +define void @foo.main() #0 { +entry: + call void @foo.test(i32 123) + call void @foo.test(i32 1) + call void @foo.test(i32 0) + ret void +} diff --git a/test/test_suite2/statements/defer_in_defer.c3t b/test/test_suite2/statements/defer_in_defer.c3t new file mode 100644 index 000000000..6d9e15b73 --- /dev/null +++ b/test/test_suite2/statements/defer_in_defer.c3t @@ -0,0 +1,38 @@ + +fn void test1() {} +fn void test2() {} +fn void test3() {} +fn void test4() {} + +fn void test() +{ + defer + { + defer test1(); + test2(); + defer test3(); + } + test4(); +} + +fn void test_line() +{ + defer { defer test1(); } +} + +// #expect: defer_in_defer.ll + +define void @defer_in_defer.test() #0 { +entry: + call void @defer_in_defer.test4() + call void @defer_in_defer.test2() + call void @defer_in_defer.test3() + call void @defer_in_defer.test1() + ret void +} + +define void @defer_in_defer.test_line() #0 { +entry: + call void @defer_in_defer.test1() + ret void +} diff --git a/test/test_suite2/statements/defer_in_defer2.c3t b/test/test_suite2/statements/defer_in_defer2.c3t new file mode 100644 index 000000000..5de8af3a3 --- /dev/null +++ b/test/test_suite2/statements/defer_in_defer2.c3t @@ -0,0 +1,120 @@ +// #target: macos-x64 + +module test; +extern fn void printf(char*,...); + +fn void test(int x) +{ + defer + { + do + { + defer printf("Hello %d\n", x); + x *= 2; + if (x < 100) break; + x *= 10000; + }; + } + if (x == 1) + { + printf("1x\n"); + return; + } + if (x == 0) return; +} + +fn void main() +{ + test(123); + test(1); + test(0); +} + +/* #expect: test.ll + +define void @test.test(i32 %0) #0 { +entry: + %x = alloca i32, align 4 + store i32 %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %eq = icmp eq i32 %1, 1 + br i1 %eq, label %if.then, label %if.exit3 + +if.then: ; preds = %entry + call void (ptr, ...) @printf(ptr @.str) + %2 = load i32, ptr %x, align 4 + %mul = mul i32 %2, 2 + store i32 %mul, ptr %x, align 4 + %3 = load i32, ptr %x, align 4 + %lt = icmp slt i32 %3, 100 + br i1 %lt, label %if.then1, label %if.exit + +if.then1: ; preds = %if.then + %4 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %4) + br label %loop.exit + +if.exit: ; preds = %if.then + %5 = load i32, ptr %x, align 4 + %mul2 = mul i32 %5, 10000 + store i32 %mul2, ptr %x, align 4 + %6 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %6) + br label %loop.exit + +loop.exit: ; preds = %if.exit, %if.then1 + ret void + +if.exit3: ; preds = %entry + %7 = load i32, ptr %x, align 4 + %eq4 = icmp eq i32 %7, 0 + br i1 %eq4, label %if.then5, label %if.exit12 + +if.then5: ; preds = %if.exit3 + %8 = load i32, ptr %x, align 4 + %mul6 = mul i32 %8, 2 + store i32 %mul6, ptr %x, align 4 + %9 = load i32, ptr %x, align 4 + %lt7 = icmp slt i32 %9, 100 + br i1 %lt7, label %if.then8, label %if.exit9 + +if.then8: ; preds = %if.then5 + %10 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %10) + br label %loop.exit11 + +if.exit9: ; preds = %if.then5 + %11 = load i32, ptr %x, align 4 + %mul10 = mul i32 %11, 10000 + store i32 %mul10, ptr %x, align 4 + %12 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %12) + br label %loop.exit11 + +loop.exit11: ; preds = %if.exit9, %if.then8 + ret void + +if.exit12: ; preds = %if.exit3 + %13 = load i32, ptr %x, align 4 + %mul13 = mul i32 %13, 2 + store i32 %mul13, ptr %x, align 4 + %14 = load i32, ptr %x, align 4 + %lt14 = icmp slt i32 %14, 100 + br i1 %lt14, label %if.then15, label %if.exit16 + +if.then15: ; preds = %if.exit12 + %15 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %15) + br label %loop.exit18 + +if.exit16: ; preds = %if.exit12 + %16 = load i32, ptr %x, align 4 + %mul17 = mul i32 %16, 10000 + store i32 %mul17, ptr %x, align 4 + %17 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %17) + br label %loop.exit18 + +loop.exit18: ; preds = %if.exit16, %if.then15 + ret void +} diff --git a/test/test_suite2/statements/defer_next_switch.c3t b/test/test_suite2/statements/defer_next_switch.c3t new file mode 100644 index 000000000..011484cd5 --- /dev/null +++ b/test/test_suite2/statements/defer_next_switch.c3t @@ -0,0 +1,59 @@ + +fn void test1() +{} + +fn void test2() +{} + +fn void test(int i) +{ + bool b = true; + switch (i) + { + case 1: + defer test2(); + if (b) nextcase; + test1(); + case 2: + test1(); + } +} + +/* #expect: defer_next_switch.ll + +define void @defer_next_switch.test(i32 %0) #0 { +entry: + %b = alloca i8, align 1 + %switch = alloca i32, align 4 + store i8 1, ptr %b, align 1 + store i32 %0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %1 = load i32, ptr %switch, align 4 + switch i32 %1, label %switch.exit [ + i32 1, label %switch.case + i32 2, label %switch.case1 + ] + +switch.case: ; preds = %switch.entry + %2 = load i8, ptr %b, align 1 + %3 = trunc i8 %2 to i1 + br i1 %3, label %if.then, label %if.exit + +if.then: ; preds = %switch.case + call void @defer_next_switch.test2() + br label %switch.case1 + +if.exit: ; preds = %switch.case + call void @defer_next_switch.test1() + call void @defer_next_switch.test2() + br label %switch.exit + +switch.case1: ; preds = %switch.entry, %if.then + call void @defer_next_switch.test1() + br label %switch.exit + +switch.exit: ; preds = %switch.case1, %if.exit, %switch.entry + ret void +} diff --git a/test/test_suite2/statements/defer_return.c3t b/test/test_suite2/statements/defer_return.c3t new file mode 100644 index 000000000..9d9c43d6f --- /dev/null +++ b/test/test_suite2/statements/defer_return.c3t @@ -0,0 +1,100 @@ +// #target: macos-x64 +module test; +fn void test1() {} +fn void test2() {} +fn void test3() {} +fn void test4() {} +fn void test5() {} +fn void test6() {} +fn void test7() {} +fn void test8() {} +fn void test9() {} + +fn int main(int argc, char **argv) +{ + defer test1(); + int a = 0; + while (a) + { + defer test2(); + if (argc == 1) return a + argc; + defer test3(); + test4(); + } + defer test5(); + while (a) + { + defer test6(); + if (argc == 1) return a + 2; + defer test7(); + test8(); + return 2 + 2; + defer test9(); + } + return 0 + argc; +} + +/* #expect: test.ll + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + %a = alloca i32, align 4 + store i32 0, ptr %a, align 4 + br label %loop.cond + +loop.cond: ; preds = %if.exit, %entry + %2 = load i32, ptr %a, align 4 + %intbool = icmp ne i32 %2, 0 + br i1 %intbool, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %eq = icmp eq i32 %0, 1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + %3 = load i32, ptr %a, align 4 + %add = add i32 %3, %0 + call void @test.test2() + call void @test.test1() + ret i32 %add + +if.exit: ; preds = %loop.body + call void @test.test4() + call void @test.test3() + call void @test.test2() + br label %loop.cond + +loop.exit: ; preds = %loop.cond + br label %loop.cond1 + +loop.cond1: ; preds = %loop.exit + %4 = load i32, ptr %a, align 4 + %intbool2 = icmp ne i32 %4, 0 + br i1 %intbool2, label %loop.body3, label %loop.exit8 + +loop.body3: ; preds = %loop.cond1 + %eq4 = icmp eq i32 %0, 1 + br i1 %eq4, label %if.then5, label %if.exit7 + +if.then5: ; preds = %loop.body3 + %5 = load i32, ptr %a, align 4 + %add6 = add i32 %5, 2 + call void @test.test6() + call void @test.test5() + call void @test.test1() + ret i32 %add6 + +if.exit7: ; preds = %loop.body3 + call void @test.test8() + call void @test.test7() + call void @test.test6() + call void @test.test5() + call void @test.test1() + ret i32 4 + +loop.exit8: ; preds = %loop.cond1 + %add9 = add i32 0, %0 + call void @test.test5() + call void @test.test1() + ret i32 %add9 +} \ No newline at end of file diff --git a/test/test_suite2/statements/defer_test.c3 b/test/test_suite2/statements/defer_test.c3 new file mode 100644 index 000000000..81b9bf3e9 --- /dev/null +++ b/test/test_suite2/statements/defer_test.c3 @@ -0,0 +1,9 @@ +fn void test() +{ + int i = 0; + defer + { + i = i + 1; + } + return; +} \ No newline at end of file diff --git a/test/test_suite2/statements/defer_with_loop.c3t b/test/test_suite2/statements/defer_with_loop.c3t new file mode 100644 index 000000000..be69a28bc --- /dev/null +++ b/test/test_suite2/statements/defer_with_loop.c3t @@ -0,0 +1,108 @@ +// #target: macos-x64 +module test; + +extern fn void printf(char*,...); + +fn void test(int x) +{ + defer + { + for (int i = 0; i < 3; i++) + { + printf("%d\n", x + i); + } + } + if (x == 1) + { + printf("1x\n"); + return; + } + if (x == 0) return; +} + +fn void main() +{ + test(123); + test(1); + test(0); +} + +/* #expect: test.ll + +define void @test.test(i32 %0) #0 { +entry: + %i = alloca i32, align 4 + %i4 = alloca i32, align 4 + %i12 = alloca i32, align 4 + %eq = icmp eq i32 %0, 1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + call void (ptr, ...) @printf(ptr @.str) + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %if.then + %1 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %1, 3 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %2 = load i32, ptr %i, align 4 + %add = add i32 %0, %2 + call void (ptr, ...) @printf(ptr @.str.1, i32 %add) + %3 = load i32, ptr %i, align 4 + %add1 = add i32 %3, 1 + store i32 %add1, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void + +if.exit: ; preds = %entry + %eq2 = icmp eq i32 %0, 0 + br i1 %eq2, label %if.then3, label %if.exit11 + +if.then3: ; preds = %if.exit + store i32 0, ptr %i4, align 4 + br label %loop.cond5 + +loop.cond5: ; preds = %loop.body7, %if.then3 + %4 = load i32, ptr %i4, align 4 + %lt6 = icmp slt i32 %4, 3 + br i1 %lt6, label %loop.body7, label %loop.exit10 + +loop.body7: ; preds = %loop.cond5 + %5 = load i32, ptr %i4, align 4 + %add8 = add i32 %0, %5 + call void (ptr, ...) @printf(ptr @.str.2, i32 %add8) + %6 = load i32, ptr %i4, align 4 + %add9 = add i32 %6, 1 + store i32 %add9, ptr %i4, align 4 + br label %loop.cond5 + +loop.exit10: ; preds = %loop.cond5 + ret void + +if.exit11: ; preds = %if.exit + store i32 0, ptr %i12, align 4 + br label %loop.cond13 + +loop.cond13: ; preds = %loop.body15, %if.exit11 + %7 = load i32, ptr %i12, align 4 + %lt14 = icmp slt i32 %7, 3 + br i1 %lt14, label %loop.body15, label %loop.exit18 + +loop.body15: ; preds = %loop.cond13 + %8 = load i32, ptr %i12, align 4 + %add16 = add i32 %0, %8 + call void (ptr, ...) @printf(ptr @.str.3, i32 %add16) + %9 = load i32, ptr %i12, align 4 + %add17 = add i32 %9, 1 + store i32 %add17, ptr %i12, align 4 + br label %loop.cond13 + +loop.exit18: ; preds = %loop.cond13 + ret void +} + diff --git a/test/test_suite2/statements/do_without_compound.c3 b/test/test_suite2/statements/do_without_compound.c3 new file mode 100644 index 000000000..b37b73729 --- /dev/null +++ b/test/test_suite2/statements/do_without_compound.c3 @@ -0,0 +1,5 @@ +fn void test1() +{ + do test1(); while(1); // #error: A do loop must use { } around its body +} + diff --git a/test/test_suite2/statements/fallthough_do.c3t b/test/test_suite2/statements/fallthough_do.c3t new file mode 100644 index 000000000..0cc625ab7 --- /dev/null +++ b/test/test_suite2/statements/fallthough_do.c3t @@ -0,0 +1,81 @@ +// #target: macos-x64 + +module foo; +fn int test() +{ + static int x = 0; + return 1 + x++; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + int i = 10; + do + { + printf("%d\n", test()); + } while (false); + do + { + printf("%d, %d\n", i, test()); + }; + do + { + if (i < 0) continue; + printf("A\n", i, test()); + }; + do + { + if (i < 0) break; + printf("B\n", i, test()); + }; + +} + +/* #expect: foo.ll + + +@test.x = internal unnamed_addr global i32 0, align 4 +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@.str.1 = private unnamed_addr constant [8 x i8] c"%d, %d\0A\00", align 1 + +define void @foo.main() #0 { +entry: + %i = alloca i32, align 4 + store i32 10, ptr %i, align 4 + %0 = call i32 @foo.test() + call void (ptr, ...) @printf(ptr @.str, i32 %0) + %1 = load i32, ptr %i, align 4 + %2 = call i32 @foo.test() + call void (ptr, ...) @printf(ptr @.str.1, i32 %1, i32 %2) + %3 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %3, 0 + br i1 %lt, label %if.then, label %if.exit + +if.then: ; preds = %entry + br label %loop.exit + +if.exit: ; preds = %entry + %4 = load i32, ptr %i, align 4 + %5 = call i32 @foo.test() + call void (ptr, ...) @printf(ptr @.str.2, i32 %4, i32 %5) + br label %loop.exit + +loop.exit: ; preds = %if.exit, %if.then + %6 = load i32, ptr %i, align 4 + %lt1 = icmp slt i32 %6, 0 + br i1 %lt1, label %if.then2, label %if.exit3 + +if.then2: ; preds = %loop.exit + br label %loop.exit4 + +if.exit3: ; preds = %loop.exit + %7 = load i32, ptr %i, align 4 + %8 = call i32 @foo.test() + call void (ptr, ...) @printf(ptr @.str.3, i32 %7, i32 %8) + br label %loop.exit4 + +loop.exit4: ; preds = %if.exit3, %if.then2 + ret void +} diff --git a/test/test_suite2/statements/for.c3 b/test/test_suite2/statements/for.c3 new file mode 100644 index 000000000..3dc2e9a52 --- /dev/null +++ b/test/test_suite2/statements/for.c3 @@ -0,0 +1,27 @@ +module for_test; + + + +fn int test1() +{ + for (int x = 0;;) + { + } + return 0; +} + +fn int test2() +{ + for (int x = 0; 1 ;) + { + } + return 0; +} + +fn int test3() +{ + for (; 1 ;2) + { + } + return 0; +} diff --git a/test/test_suite2/statements/for_empty.c3 b/test/test_suite2/statements/for_empty.c3 new file mode 100644 index 000000000..3536032da --- /dev/null +++ b/test/test_suite2/statements/for_empty.c3 @@ -0,0 +1,7 @@ +fn int main() +{ + for (;;); + + for (;;) {} + return 0; +} \ No newline at end of file diff --git a/test/test_suite2/statements/for_errors.c3 b/test/test_suite2/statements/for_errors.c3 new file mode 100644 index 000000000..c013a65bc --- /dev/null +++ b/test/test_suite2/statements/for_errors.c3 @@ -0,0 +1,7 @@ +fn void foo() {} + +fn int main() +{ + for (; foo() ; ) {} // #error: Expected a boolean expression + return 0; +} \ No newline at end of file diff --git a/test/test_suite2/statements/for_with_extra_declarations.c3 b/test/test_suite2/statements/for_with_extra_declarations.c3 new file mode 100644 index 000000000..12a04a1f7 --- /dev/null +++ b/test/test_suite2/statements/for_with_extra_declarations.c3 @@ -0,0 +1,17 @@ +fn void test() +{ + int j; + for (int i = 0; i < 10; i++) + { + + } + for (int i = 0, int foo = 0; i < 10; i++) + { + + } + + for (int i = 0, j = 1; i < 10; i++, j++) + { + + } +} \ No newline at end of file diff --git a/test/test_suite2/statements/foreach_break.c3t b/test/test_suite2/statements/foreach_break.c3t new file mode 100644 index 000000000..6727ef55b --- /dev/null +++ b/test/test_suite2/statements/foreach_break.c3t @@ -0,0 +1,74 @@ +// #target: macos-x64 +module test; + +fn void test() +{ + int[3] x; + int g = 0; + foreach (z : x) + { + if (z > 0) break; + if (z == 1) continue; + g += z; + } +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + %x = alloca [3 x i32], align 4 + %g = alloca i32, align 4 + %anon = alloca i64, align 8 + %z = alloca i32, align 4 + %0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 0 + store i32 0, ptr %0, align 4 + %1 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + store i32 0, ptr %1, align 4 + %2 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 2 + store i32 0, ptr %2, align 4 + store i32 0, ptr %g, align 4 + store i64 0, ptr %anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.inc, %entry + %3 = load i64, ptr %anon, align 8 + %gt = icmp ugt i64 3, %3 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %4 = load i64, ptr %anon, align 8 + %5 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 %4 + %6 = load i32, ptr %5, align 4 + store i32 %6, ptr %z, align 4 + %7 = load i32, ptr %z, align 4 + %gt1 = icmp sgt i32 %7, 0 + br i1 %gt1, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + br label %loop.exit + +if.exit: ; preds = %loop.body + %8 = load i32, ptr %z, align 4 + %eq = icmp eq i32 %8, 1 + br i1 %eq, label %if.then2, label %if.exit3 + +if.then2: ; preds = %if.exit + br label %loop.inc + +if.exit3: ; preds = %if.exit + %9 = load i32, ptr %g, align 4 + %10 = load i32, ptr %z, align 4 + %add = add i32 %9, %10 + store i32 %add, ptr %g, align 4 + br label %loop.inc + +loop.inc: ; preds = %if.exit3, %if.then2 + %11 = load i64, ptr %anon, align 8 + %add4 = add i64 %11, 1 + store i64 %add4, ptr %anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %if.then, %loop.cond + ret void +} \ No newline at end of file diff --git a/test/test_suite2/statements/foreach_common.c3t b/test/test_suite2/statements/foreach_common.c3t new file mode 100644 index 000000000..6af3798ae --- /dev/null +++ b/test/test_suite2/statements/foreach_common.c3t @@ -0,0 +1,366 @@ +// #target: macos-x64 +module test; + +extern fn void printf(char*, ...); + +fn void main() +{ + float[3] foo = { 2, 4.5, 8 }; + float[<3>] foo2 = { 2, 4.5, 8 }; + foreach (a : foo) + { + printf("Value: %f\n", a); + } + foreach (float* &a : foo) + { + *a *= 2; + printf("Value: %f\n", *a); + } + foreach (void* &a : foo) + { + printf("Value: %f\n", *((float*)(a))); + } + foreach (i, a : foo) + { + printf("Value[%d]: %f\n", i, a); + } + foreach (char i, double a : foo) + { + printf("Value2[%d]: %f\n", i, a); + } + foreach (double a : foo) + { + printf("Value3: %f\n", a); + } + + foreach (a : foo2) + { + printf("Value: %f\n", a); + } + foreach (i, a : foo2) + { + printf("Value[%d]: %f\n", i, a); + } + foreach (char i, double a : foo2) + { + printf("Value2[%d]: %f\n", i, a); + } + foreach (double a : foo2) + { + printf("Value3: %f\n", a); + } +} + +/* #expect: test.ll + +source_filename = "test" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +@.__const = private unnamed_addr constant [3 x float] [float 2.000000e+00, float 4.500000e+00, float 8.000000e+00], align 4 +@.str = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1 +@.str.1 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1 +@.str.2 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1 +@.str.3 = private unnamed_addr constant [15 x i8] c"Value[%d]: %f\0A\00", align 1 +@.str.4 = private unnamed_addr constant [16 x i8] c"Value2[%d]: %f\0A\00", align 1 +@.str.5 = private unnamed_addr constant [12 x i8] c"Value3: %f\0A\00", align 1 +@.str.6 = private unnamed_addr constant [11 x i8] c"Value: %f\0A\00", align 1 +@.str.7 = private unnamed_addr constant [15 x i8] c"Value[%d]: %f\0A\00", align 1 +@.str.8 = private unnamed_addr constant [16 x i8] c"Value2[%d]: %f\0A\00", align 1 +@.str.9 = private unnamed_addr constant [12 x i8] c"Value3: %f\0A\00", align 1 + +; Function Attrs: nounwind +declare void @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @test.main() #0 { +entry: + %foo = alloca [3 x float], align 4 + %foo2 = alloca <3 x float>, align 16 + %anon = alloca i64, align 8 + %a = alloca float, align 4 + %anon1 = alloca i64, align 8 + %a5 = alloca ptr, align 8 + %anon9 = alloca i64, align 8 + %a13 = alloca ptr, align 8 + %anon17 = alloca i64, align 8 + %i = alloca i64, align 8 + %a21 = alloca float, align 4 + %anon25 = alloca i64, align 8 + %i29 = alloca i8, align 1 + %a30 = alloca double, align 8 + %anon34 = alloca i64, align 8 + %a38 = alloca double, align 8 + %anon42 = alloca i64, align 8 + %anon43 = alloca i64, align 8 + %a46 = alloca float, align 4 + %anon50 = alloca i64, align 8 + %anon51 = alloca i64, align 8 + %i55 = alloca i64, align 8 + %a56 = alloca float, align 4 + %anon60 = alloca i64, align 8 + %anon61 = alloca i64, align 8 + %i65 = alloca i8, align 1 + %a67 = alloca double, align 8 + %anon72 = alloca i64, align 8 + %anon73 = alloca i64, align 8 + %a77 = alloca double, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %foo, ptr align 4 @.__const, i32 12, i1 false) + store <3 x float> , ptr %foo2, align 16 + store i64 0, ptr %anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %0 = load i64, ptr %anon, align 8 + %gt = icmp ugt i64 3, %0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %anon, align 8 + %2 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %1 + %3 = load float, ptr %2, align 4 + store float %3, ptr %a, align 4 + %4 = load float, ptr %a, align 4 + %fpfpext = fpext float %4 to double + call void (ptr, ...) @printf(ptr @.str, double %fpfpext) + %5 = load i64, ptr %anon, align 8 + %add = add i64 %5, 1 + store i64 %add, ptr %anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + store i64 0, ptr %anon1, align 8 + br label %loop.cond2 + +loop.cond2: ; preds = %loop.body4, %loop.exit + %6 = load i64, ptr %anon1, align 8 + %gt3 = icmp ugt i64 3, %6 + br i1 %gt3, label %loop.body4, label %loop.exit8 + +loop.body4: ; preds = %loop.cond2 + %7 = load i64, ptr %anon1, align 8 + %8 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %7 + store ptr %8, ptr %a5, align 8 + %9 = load ptr, ptr %a5, align 8 + %10 = load float, ptr %9, align 8 + %fmul = fmul float %10, 2.000000e+00 + store float %fmul, ptr %9, align 8 + %11 = load ptr, ptr %a5, align 8 + %12 = load float, ptr %11, align 8 + %fpfpext6 = fpext float %12 to double + call void (ptr, ...) @printf(ptr @.str.1, double %fpfpext6) + %13 = load i64, ptr %anon1, align 8 + %add7 = add i64 %13, 1 + store i64 %add7, ptr %anon1, align 8 + br label %loop.cond2 + +loop.exit8: ; preds = %loop.cond2 + store i64 0, ptr %anon9, align 8 + br label %loop.cond10 + +loop.cond10: ; preds = %loop.body12, %loop.exit8 + %14 = load i64, ptr %anon9, align 8 + %gt11 = icmp ugt i64 3, %14 + br i1 %gt11, label %loop.body12, label %loop.exit16 + +loop.body12: ; preds = %loop.cond10 + %15 = load i64, ptr %anon9, align 8 + %16 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %15 + store ptr %16, ptr %a13, align 8 + %17 = load ptr, ptr %a13, align 8 + %18 = load float, ptr %17, align 8 + %fpfpext14 = fpext float %18 to double + call void (ptr, ...) @printf(ptr @.str.2, double %fpfpext14) + %19 = load i64, ptr %anon9, align 8 + %add15 = add i64 %19, 1 + store i64 %add15, ptr %anon9, align 8 + br label %loop.cond10 + +loop.exit16: ; preds = %loop.cond10 + store i64 0, ptr %anon17, align 8 + br label %loop.cond18 + +loop.cond18: ; preds = %loop.body20, %loop.exit16 + %20 = load i64, ptr %anon17, align 8 + %gt19 = icmp ugt i64 3, %20 + br i1 %gt19, label %loop.body20, label %loop.exit24 + +loop.body20: ; preds = %loop.cond18 + %21 = load i64, ptr %anon17, align 8 + store i64 %21, ptr %i, align 8 + %22 = load i64, ptr %anon17, align 8 + %23 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %22 + %24 = load float, ptr %23, align 4 + store float %24, ptr %a21, align 4 + %25 = load i64, ptr %i, align 8 + %26 = load float, ptr %a21, align 4 + %fpfpext22 = fpext float %26 to double + call void (ptr, ...) @printf(ptr @.str.3, i64 %25, double %fpfpext22) + %27 = load i64, ptr %anon17, align 8 + %add23 = add i64 %27, 1 + store i64 %add23, ptr %anon17, align 8 + br label %loop.cond18 + +loop.exit24: ; preds = %loop.cond18 + store i64 0, ptr %anon25, align 8 + br label %loop.cond26 + +loop.cond26: ; preds = %loop.body28, %loop.exit24 + %28 = load i64, ptr %anon25, align 8 + %gt27 = icmp ugt i64 3, %28 + br i1 %gt27, label %loop.body28, label %loop.exit33 + +loop.body28: ; preds = %loop.cond26 + %29 = load i64, ptr %anon25, align 8 + %uiuitrunc = trunc i64 %29 to i8 + store i8 %uiuitrunc, ptr %i29, align 1 + %30 = load i64, ptr %anon25, align 8 + %31 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %30 + %32 = load float, ptr %31, align 4 + %fpfpext31 = fpext float %32 to double + store double %fpfpext31, ptr %a30, align 8 + %33 = load i8, ptr %i29, align 1 + %uisiext = zext i8 %33 to i32 + %34 = load double, ptr %a30, align 8 + call void (ptr, ...) @printf(ptr @.str.4, i32 %uisiext, double %34) + %35 = load i64, ptr %anon25, align 8 + %add32 = add i64 %35, 1 + store i64 %add32, ptr %anon25, align 8 + br label %loop.cond26 + +loop.exit33: ; preds = %loop.cond26 + store i64 0, ptr %anon34, align 8 + br label %loop.cond35 + +loop.cond35: ; preds = %loop.body37, %loop.exit33 + %36 = load i64, ptr %anon34, align 8 + %gt36 = icmp ugt i64 3, %36 + br i1 %gt36, label %loop.body37, label %loop.exit41 + +loop.body37: ; preds = %loop.cond35 + %37 = load i64, ptr %anon34, align 8 + %38 = getelementptr inbounds [3 x float], ptr %foo, i64 0, i64 %37 + %39 = load float, ptr %38, align 4 + %fpfpext39 = fpext float %39 to double + store double %fpfpext39, ptr %a38, align 8 + %40 = load double, ptr %a38, align 8 + call void (ptr, ...) @printf(ptr @.str.5, double %40) + %41 = load i64, ptr %anon34, align 8 + %add40 = add i64 %41, 1 + store i64 %add40, ptr %anon34, align 8 + br label %loop.cond35 + +loop.exit41: ; preds = %loop.cond35 + store i64 0, ptr %anon42, align 8 + store i64 3, ptr %anon43, align 8 + br label %loop.cond44 + +loop.cond44: ; preds = %loop.body45, %loop.exit41 + %42 = load i64, ptr %anon42, align 8 + %43 = load i64, ptr %anon43, align 8 + %lt = icmp ult i64 %42, %43 + br i1 %lt, label %loop.body45, label %loop.exit49 + +loop.body45: ; preds = %loop.cond44 + %44 = load <3 x float>, ptr %foo2, align 16 + %45 = load i64, ptr %anon42, align 8 + %46 = extractelement <3 x float> %44, i64 %45 + store float %46, ptr %a46, align 4 + %47 = load float, ptr %a46, align 4 + %fpfpext47 = fpext float %47 to double + call void (ptr, ...) @printf(ptr @.str.6, double %fpfpext47) + %48 = load i64, ptr %anon42, align 8 + %add48 = add i64 %48, 1 + store i64 %add48, ptr %anon42, align 8 + br label %loop.cond44 + +loop.exit49: ; preds = %loop.cond44 + store i64 0, ptr %anon50, align 8 + store i64 3, ptr %anon51, align 8 + br label %loop.cond52 + +loop.cond52: ; preds = %loop.body54, %loop.exit49 + %49 = load i64, ptr %anon50, align 8 + %50 = load i64, ptr %anon51, align 8 + %lt53 = icmp ult i64 %49, %50 + br i1 %lt53, label %loop.body54, label %loop.exit59 + +loop.body54: ; preds = %loop.cond52 + %51 = load i64, ptr %anon50, align 8 + store i64 %51, ptr %i55, align 8 + %52 = load <3 x float>, ptr %foo2, align 16 + %53 = load i64, ptr %anon50, align 8 + %54 = extractelement <3 x float> %52, i64 %53 + store float %54, ptr %a56, align 4 + %55 = load i64, ptr %i55, align 8 + %56 = load float, ptr %a56, align 4 + %fpfpext57 = fpext float %56 to double + call void (ptr, ...) @printf(ptr @.str.7, i64 %55, double %fpfpext57) + %57 = load i64, ptr %anon50, align 8 + %add58 = add i64 %57, 1 + store i64 %add58, ptr %anon50, align 8 + br label %loop.cond52 + +loop.exit59: ; preds = %loop.cond52 + store i64 0, ptr %anon60, align 8 + store i64 3, ptr %anon61, align 8 + br label %loop.cond62 + +loop.cond62: ; preds = %loop.body64, %loop.exit59 + %58 = load i64, ptr %anon60, align 8 + %59 = load i64, ptr %anon61, align 8 + %lt63 = icmp ult i64 %58, %59 + br i1 %lt63, label %loop.body64, label %loop.exit71 + +loop.body64: ; preds = %loop.cond62 + %60 = load i64, ptr %anon60, align 8 + %uiuitrunc66 = trunc i64 %60 to i8 + store i8 %uiuitrunc66, ptr %i65, align 1 + %61 = load <3 x float>, ptr %foo2, align 16 + %62 = load i64, ptr %anon60, align 8 + %63 = extractelement <3 x float> %61, i64 %62 + %fpfpext68 = fpext float %63 to double + store double %fpfpext68, ptr %a67, align 8 + %64 = load i8, ptr %i65, align 1 + %uisiext69 = zext i8 %64 to i32 + %65 = load double, ptr %a67, align 8 + call void (ptr, ...) @printf(ptr @.str.8, i32 %uisiext69, double %65) + %66 = load i64, ptr %anon60, align 8 + %add70 = add i64 %66, 1 + store i64 %add70, ptr %anon60, align 8 + br label %loop.cond62 + +loop.exit71: ; preds = %loop.cond62 + store i64 0, ptr %anon72, align 8 + store i64 3, ptr %anon73, align 8 + br label %loop.cond74 + +loop.cond74: ; preds = %loop.body76, %loop.exit71 + %67 = load i64, ptr %anon72, align 8 + %68 = load i64, ptr %anon73, align 8 + %lt75 = icmp ult i64 %67, %68 + br i1 %lt75, label %loop.body76, label %loop.exit80 + +loop.body76: ; preds = %loop.cond74 + %69 = load <3 x float>, ptr %foo2, align 16 + %70 = load i64, ptr %anon72, align 8 + %71 = extractelement <3 x float> %69, i64 %70 + %fpfpext78 = fpext float %71 to double + store double %fpfpext78, ptr %a77, align 8 + %72 = load double, ptr %a77, align 8 + call void (ptr, ...) @printf(ptr @.str.9, double %72) + %73 = load i64, ptr %anon72, align 8 + %add79 = add i64 %73, 1 + store i64 %add79, ptr %anon72, align 8 + br label %loop.cond74 + +loop.exit80: ; preds = %loop.cond74 + ret void +} + +; Function Attrs: nounwind +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} diff --git a/test/test_suite2/statements/foreach_custom.c3t b/test/test_suite2/statements/foreach_custom.c3t new file mode 100644 index 000000000..8f5a6c68c --- /dev/null +++ b/test/test_suite2/statements/foreach_custom.c3t @@ -0,0 +1,82 @@ +// #target: macos-x64 + +module foo; +struct Foo +{ + int[] x; +} + +macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat) +{ + return foo.x[index]; +} + +macro usize Foo.@operator_len(Foo &foo) @operator(len) +{ + return foo.x.len; +} + +fn void main() +{ + int[*] i = { 1, 3, 10 }; + Foo x = { &i }; + foreach FOO: (int f : x) { + printf("%d\n", f); + while (1) + { + break FOO; + } + } +} + +extern fn int printf(char *fmt, ...); + +/* #expect: foo.ll + +; Function Attrs: nounwind +define void @foo.main() #0 { +entry: + %i = alloca [3 x i32], align 4 + %x = alloca %Foo, align 8 + %anon = alloca i64, align 8 + %anon1 = alloca i64, align 8 + %f = alloca i32, align 4 + %index = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %i, ptr align 4 @.__const, i32 12, i1 false) + %0 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %1 = insertvalue %"int[]" undef, ptr %i, 0 + %2 = insertvalue %"int[]" %1, i64 3, 1 + store %"int[]" %2, ptr %0, align 8 + store i64 0, ptr %anon, align 8 + %3 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %4 = getelementptr inbounds %"int[]", ptr %3, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %anon1, align 8 + br label %loop.cond + +loop.cond: ; preds = %entry + %6 = load i64, ptr %anon, align 8 + %7 = load i64, ptr %anon1, align 8 + %lt = icmp ult i64 %6, %7 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %8 = load i64, ptr %anon, align 8 + store i64 %8, ptr %index, align 8 + %9 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %10 = getelementptr inbounds %"int[]", ptr %9, i32 0, i32 0 + %11 = load ptr, ptr %10, align 8 + %12 = load i64, ptr %index, align 8 + %ptroffset = getelementptr inbounds i32, ptr %11, i64 %12 + %13 = load i32, ptr %ptroffset, align 4 + store i32 %13, ptr %f, align 4 + %14 = load i32, ptr %f, align 4 + %15 = call i32 (ptr, ...) @printf(ptr @.str, i32 %14) + br label %loop.body2 + +loop.body2: ; preds = %loop.body + br label %loop.exit + +loop.exit: ; preds = %loop.body2, %loop.cond + ret void +} \ No newline at end of file diff --git a/test/test_suite2/statements/foreach_custom_errors.c3 b/test/test_suite2/statements/foreach_custom_errors.c3 new file mode 100644 index 000000000..127d0df9f --- /dev/null +++ b/test/test_suite2/statements/foreach_custom_errors.c3 @@ -0,0 +1,15 @@ +fn void test1() +{ + int x; + foreach (a : x) { }; // #error: It's not possible to enumerate an expression of type 'int' +} + +define Test1 = distinct int; + +fn void test2() +{ + Test1 x; + foreach (a : x) { }; // #error: It's not possible to enumerate an expression of type 'Test1' +} + + diff --git a/test/test_suite2/statements/foreach_custom_macro.c3t b/test/test_suite2/statements/foreach_custom_macro.c3t new file mode 100644 index 000000000..1ca07214b --- /dev/null +++ b/test/test_suite2/statements/foreach_custom_macro.c3t @@ -0,0 +1,105 @@ +// #target: macos-x64 +module foo; +struct Foo +{ + int[] x; +} + +macro int Foo.@operator_element_at(Foo &foo, usize index) @operator(elementat) +{ + return foo.x[index]; +} + +macro usize Foo.@operator_len(Foo &foo) @operator(len) +{ + return foo.x.len; +} + +fn void main() +{ + int[*] i = { 1, 3, 10 }; + Foo x = { &i }; + foreach FOO: (int f : x) { + printf("%d\n", f); + while (1) + { + break FOO; + } + } +} + +extern fn int printf(char *fmt, ...); + +/* #expect: foo.ll + +source_filename = "foo" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +%Foo = type { %"int[]" } +%"int[]" = type { ptr, i64 } + +@.typeid.foo.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8 +@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 3, i32 10], align 4 +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 + +; Function Attrs: nounwind +define void @foo.main() #0 { +entry: + %i = alloca [3 x i32], align 4 + %x = alloca %Foo, align 8 + %anon = alloca i64, align 8 + %anon1 = alloca i64, align 8 + %f = alloca i32, align 4 + %index = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %i, ptr align 4 @.__const, i32 12, i1 false) + %0 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %1 = insertvalue %"int[]" undef, ptr %i, 0 + %2 = insertvalue %"int[]" %1, i64 3, 1 + store %"int[]" %2, ptr %0, align 8 + store i64 0, ptr %anon, align 8 + %3 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %4 = getelementptr inbounds %"int[]", ptr %3, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %anon1, align 8 + br label %loop.cond + +loop.cond: ; preds = %entry + %6 = load i64, ptr %anon, align 8 + %7 = load i64, ptr %anon1, align 8 + %lt = icmp ult i64 %6, %7 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %8 = load i64, ptr %anon, align 8 + store i64 %8, ptr %index, align 8 + %9 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0 + %10 = getelementptr inbounds %"int[]", ptr %9, i32 0, i32 0 + %11 = load ptr, ptr %10, align 8 + %12 = load i64, ptr %index, align 8 + %ptroffset = getelementptr inbounds i32, ptr %11, i64 %12 + %13 = load i32, ptr %ptroffset, align 4 + store i32 %13, ptr %f, align 4 + %14 = load i32, ptr %f, align 4 + %15 = call i32 (ptr, ...) @printf(ptr @.str, i32 %14) + br label %loop.body2 + +loop.body2: ; preds = %loop.body + br label %loop.exit + +loop.exit: ; preds = %loop.body2, %loop.cond + ret void +} + +; Function Attrs: nounwind +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} + +; Function Attrs: argmemonly nofree nounwind willreturn +declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #1 diff --git a/test/test_suite2/statements/foreach_errors.c3 b/test/test_suite2/statements/foreach_errors.c3 new file mode 100644 index 000000000..004dc950f --- /dev/null +++ b/test/test_suite2/statements/foreach_errors.c3 @@ -0,0 +1,54 @@ +module test; + +extern fn void foo(); +int[3] z; + +fn void test1() +{ + int x; + foreach (a : x) // #error: It's not possible to enumerate an expression of type 'int'. + { + foo(); + } +} + +fn void test2() +{ + foreach (a : z) foo(); + foreach (i, a : z) foo(); + foreach (double i, a : z); // #error: Index must be an integer type, 'double' is not valid. +} + +fn void test3() +{ + foreach (&a : z) foo(); + foreach (&i, &a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'? +} + +fn void test4() +{ + foreach (&a : z) foo(); + foreach (&i, a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'? +} + +fn void test5() +{ + foreach (int! y : z) foo(); // #error: The variable may not be a failable. +} + +fn void test6() +{ + foreach (int! i, y : z) foo(); // #error: The index may not be a failable. +} + +fn void test7() +{ + foreach (int a : { 1, 2, 3 }) foo(); + foreach (a : { 1, 2, 3 }) foo(); // #error: Add the type of your variable here if you want to iterate over +} + +fn void test8() +{ + foreach (int a : { z }) foo(); // #error: 'int[3]' into 'int' +} + diff --git a/test/test_suite2/statements/foreach_parse_error.c3 b/test/test_suite2/statements/foreach_parse_error.c3 new file mode 100644 index 000000000..4a761601a --- /dev/null +++ b/test/test_suite2/statements/foreach_parse_error.c3 @@ -0,0 +1,5 @@ +fn void test9() +{ + foreach (int a : { [2] = 1 }) foo(); + foreach (int a : { [2] = 2, 1 }) foo(); // #error: Normal initialization cannot be mixed with designated initialization. +} \ No newline at end of file diff --git a/test/test_suite2/statements/foreach_with_error.c3 b/test/test_suite2/statements/foreach_with_error.c3 new file mode 100644 index 000000000..6f8f59f7f --- /dev/null +++ b/test/test_suite2/statements/foreach_with_error.c3 @@ -0,0 +1,12 @@ +module test; + +fn void test() +{ + int[3]! x; + int g; + foreach (z : x) // #error: The expression may not be failable. + { + g += z; + x[0] = 1; + } +} diff --git a/test/test_suite2/statements/if_decl.c3 b/test/test_suite2/statements/if_decl.c3 new file mode 100644 index 000000000..ad245ec61 --- /dev/null +++ b/test/test_suite2/statements/if_decl.c3 @@ -0,0 +1,5 @@ +fn int main() +{ + if (int a) {} // #error: Expected a declaration with initializer + return 0; +} diff --git a/test/test_suite2/statements/if_single.c3 b/test/test_suite2/statements/if_single.c3 new file mode 100644 index 000000000..94ae517ca --- /dev/null +++ b/test/test_suite2/statements/if_single.c3 @@ -0,0 +1,29 @@ +fn void test() +{ + int x = 0; + if (x < 0) x++; + if (x < + 0) x++; + if (x < 0 + && x < 0) x++; + + + if (x < 0) x++; // #error: if-statements with an 'else' must use '{ }' even around a single statement. + else { x++; }; + + if (x < 0) + { + x++; + } + else x++; // #error: An 'else' must use '{ }' even around a single statement. + + if (x < 0) + { + x++; + } + else if (x > 0) + { + x++; + } + +} \ No newline at end of file diff --git a/test/test_suite2/statements/if_tests.c3t b/test/test_suite2/statements/if_tests.c3t new file mode 100644 index 000000000..5ed75c81c --- /dev/null +++ b/test/test_suite2/statements/if_tests.c3t @@ -0,0 +1,71 @@ +module iftest; + +fn void test1(int x) +{ + if (x > 0) + { + defer x += 1; + } + else + {} +} + +fn void test2(int x) +{ + if (x > 0) + { + } + else + {} +} + +fn void test3(int x) +{ + if (x > 0) + {} + else { x += 1; } +} + +// #expect: iftest.ll + +define void @iftest.test1(i32 %0) #0 { +entry: + %x = alloca i32, align 4 + store i32 %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %gt = icmp sgt i32 %1, 0 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %2 = load i32, ptr %x, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %x, align 4 + br label %if.exit + +if.exit: ; preds = %if.then, %entry + ret void +} + +define void @iftest.test2(i32 %0) #0 { +entry: + %gt = icmp sgt i32 %0, 0 + ret void +} + +define void @iftest.test3(i32 %0) #0 { +entry: + %x = alloca i32, align 4 + store i32 %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %gt = icmp sgt i32 %1, 0 + br i1 %gt, label %if.exit, label %if.else + +if.else: ; preds = %entry + %2 = load i32, ptr %x, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %x, align 4 + br label %if.exit + +if.exit: ; preds = %if.else, %entry + ret void +} \ No newline at end of file diff --git a/test/test_suite2/statements/if_while_do_error.c3 b/test/test_suite2/statements/if_while_do_error.c3 new file mode 100644 index 000000000..c0cd3312a --- /dev/null +++ b/test/test_suite2/statements/if_while_do_error.c3 @@ -0,0 +1,34 @@ +module test; + +fn void test1() +{ + bool! x = 0; + if (x) // #error: The expression may not be a failable, but was 'bool!' + { + x = 100; + } +} + +fn void test2() +{ + bool! x = 0; + while (x) // #error: The expression may not be a failable, but was 'bool!' + { + x = false; + } +} + +fn void test3() +{ + bool! x = 0; + double y = 1; + do + { + y = y + 1; + } while (y); + do + { + x = !x; + } + while (x); // #error: A failable 'bool!' cannot be implicitly converted to a regular boolean value +} \ No newline at end of file diff --git a/test/test_suite2/statements/label_errors.c3 b/test/test_suite2/statements/label_errors.c3 new file mode 100644 index 000000000..b02854bea --- /dev/null +++ b/test/test_suite2/statements/label_errors.c3 @@ -0,0 +1,24 @@ + +fn int main() +{ + do FOO: + { + while FOO: (1) // #error: would shadow a previous declaration + { + return 1; + } + }; + return 0; +} + + +fn void test1() +{ + do FOO: + { + while (1) + { + break BAR; // #error: Cannot find a labelled statement with the name 'BAR' + } + }; +} \ No newline at end of file diff --git a/test/test_suite2/statements/labelled_continue_for.c3t b/test/test_suite2/statements/labelled_continue_for.c3t new file mode 100644 index 000000000..c44a7ae9d --- /dev/null +++ b/test/test_suite2/statements/labelled_continue_for.c3t @@ -0,0 +1,71 @@ +// #target: macos-x64 +fn void errored() +{} + +fn void test() {} + +fn void testBreak() +{ + for FOO: (int i = 0; i < 10; i++) + { + for (int j = 0; j < 10; j++) + { + for BAR: (int k = 0; k < 10; k++) + { + test(); + continue FOO; + } + errored(); + } + errored(); + } +} + +/* #expect: labelled_continue_for.ll + + +define void @labelled_continue_for.testBreak() #0 { +entry: + %i = alloca i32, align 4 + %j = alloca i32, align 4 + %k = alloca i32, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond +loop.cond: ; preds = %loop.inc, %entry + %0 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %0, 10 + br i1 %lt, label %loop.body, label %loop.exit9 +loop.body: ; preds = %loop.cond + store i32 0, ptr %j, align 4 + br label %loop.cond1 +loop.cond1: ; preds = %loop.exit, %loop.body + %1 = load i32, ptr %j, align 4 + %lt2 = icmp slt i32 %1, 10 + br i1 %lt2, label %loop.body3, label %loop.exit7 +loop.body3: ; preds = %loop.cond1 + store i32 0, ptr %k, align 4 + br label %loop.cond4 +loop.cond4: ; preds = %loop.body3 + %2 = load i32, ptr %k, align 4 + %lt5 = icmp slt i32 %2, 10 + br i1 %lt5, label %loop.body6, label %loop.exit +loop.body6: ; preds = %loop.cond4 + call void @labelled_continue_for.test() + br label %loop.inc +loop.exit: ; preds = %loop.cond4 + call void @labelled_continue_for.errored() + %3 = load i32, ptr %j, align 4 + %add = add i32 %3, 1 + store i32 %add, ptr %j, align 4 + br label %loop.cond1 +loop.exit7: ; preds = %loop.cond1 + call void @labelled_continue_for.errored() + br label %loop.inc +loop.inc: ; preds = %loop.exit7, %loop.body6 + %4 = load i32, ptr %i, align 4 + %add8 = add i32 %4, 1 + store i32 %add8, ptr %i, align 4 + br label %loop.cond +loop.exit9: ; preds = %loop.cond + ret void +} diff --git a/test/test_suite2/statements/ranged_switch.c3t b/test/test_suite2/statements/ranged_switch.c3t new file mode 100644 index 000000000..759a0be07 --- /dev/null +++ b/test/test_suite2/statements/ranged_switch.c3t @@ -0,0 +1,230 @@ +// #target: macos-x64 + +module foo; + +extern fn void printf(char*, ...); + +fn void main() +{ + for (int i = 0; i < 12; i++) + { + switch (i) + { + case 1 .. 3: + printf("1-3\n"); + case 7 .. 277: + printf("7-277 %d\n", i); + case 4 .. 5: + printf("4-5 %d\n", i); + case 6: + printf("6 %d\n", i); + default: + printf("Something else: %d\n", i); + nextcase 5; + } + } + for (int i = 0; i < 12; i++) + { + switch (i) + { + case 1 .. 3: + printf("1-3\n"); + case 4 .. 6: + printf("4-6 %d\n", i); + default: + printf("Something else: %d\n", i); + nextcase 5; + } + } + bool x = false; + switch (x) + { + case true: + printf("Was true!\n"); + case false: + printf("Was false!\n"); + } +} + +/* #expect: foo.ll + +source_filename = "foo" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +@.str = private unnamed_addr constant [5 x i8] c"1-3\0A\00", align 1 +@.str.1 = private unnamed_addr constant [10 x i8] c"7-277 %d\0A\00", align 1 +@.str.2 = private unnamed_addr constant [8 x i8] c"4-5 %d\0A\00", align 1 +@.str.3 = private unnamed_addr constant [6 x i8] c"6 %d\0A\00", align 1 +@.str.4 = private unnamed_addr constant [20 x i8] c"Something else: %d\0A\00", align 1 +@.str.5 = private unnamed_addr constant [5 x i8] c"1-3\0A\00", align 1 +@.str.6 = private unnamed_addr constant [8 x i8] c"4-6 %d\0A\00", align 1 +@.str.7 = private unnamed_addr constant [20 x i8] c"Something else: %d\0A\00", align 1 +@.str.8 = private unnamed_addr constant [11 x i8] c"Was true!\0A\00", align 1 +@.str.9 = private unnamed_addr constant [12 x i8] c"Was false!\0A\00", align 1 + +; Function Attrs: nounwind +declare void @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @foo.main() #0 { +entry: + %i = alloca i32, align 4 + %switch = alloca i32, align 4 + %i11 = alloca i32, align 4 + %switch15 = alloca i32, align 4 + %x = alloca i8, align 1 + %switch23 = alloca i8, align 1 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %switch.exit, %entry + %0 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %0, 12 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i32, ptr %i, align 4 + store i32 %1, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %loop.body + %2 = load i32, ptr %switch, align 4 + %le = icmp sle i32 1, %2 + %ge = icmp sge i32 3, %2 + %3 = and i1 %le, %ge + br i1 %3, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + call void (ptr, ...) @printf(ptr @.str) + br label %switch.exit + +next_if: ; preds = %switch.entry + %le1 = icmp sle i32 7, %2 + %ge2 = icmp sge i32 277, %2 + %4 = and i1 %le1, %ge2 + br i1 %4, label %switch.case3, label %next_if4 + +switch.case3: ; preds = %next_if + %5 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %5) + br label %switch.exit + +next_if4: ; preds = %next_if + %le5 = icmp sle i32 4, %2 + %ge6 = icmp sge i32 5, %2 + %6 = and i1 %le5, %ge6 + br i1 %6, label %switch.case7, label %next_if8 + +switch.case7: ; preds = %switch.default, %next_if4 + %7 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %7) + br label %switch.exit + +next_if8: ; preds = %next_if4 + %eq = icmp eq i32 6, %2 + br i1 %eq, label %switch.case9, label %next_if10 + +switch.case9: ; preds = %next_if8 + %8 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %8) + br label %switch.exit + +next_if10: ; preds = %next_if8 + br label %switch.default + +switch.default: ; preds = %next_if10 + %9 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %9) + br label %switch.case7 + +switch.exit: ; preds = %switch.case9, %switch.case7, %switch.case3, %switch.case + %10 = load i32, ptr %i, align 4 + %add = add i32 %10, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + store i32 0, ptr %i11, align 4 + br label %loop.cond12 + +loop.cond12: ; preds = %switch.exit20, %loop.exit + %11 = load i32, ptr %i11, align 4 + %lt13 = icmp slt i32 %11, 12 + br i1 %lt13, label %loop.body14, label %loop.exit22 + +loop.body14: ; preds = %loop.cond12 + %12 = load i32, ptr %i11, align 4 + store i32 %12, ptr %switch15, align 4 + br label %switch.entry16 + +switch.entry16: ; preds = %loop.body14 + %13 = load i32, ptr %switch15, align 4 + switch i32 %13, label %switch.default19 [ + i32 1, label %switch.case17 + i32 2, label %switch.case17 + i32 3, label %switch.case17 + i32 4, label %switch.case18 + i32 5, label %switch.case18 + i32 6, label %switch.case18 + ] + +switch.case17: ; preds = %switch.entry16, %switch.entry16, %switch.entry16 + call void (ptr, ...) @printf(ptr @.str.5) + br label %switch.exit20 + +switch.case18: ; preds = %switch.default19, %switch.entry16, %switch.entry16, %switch.entry16 + %14 = load i32, ptr %i11, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %14) + br label %switch.exit20 + +switch.default19: ; preds = %switch.entry16 + %15 = load i32, ptr %i11, align 4 + call void (ptr, ...) @printf(ptr @.str.7, i32 %15) + br label %switch.case18 + +switch.exit20: ; preds = %switch.case18, %switch.case17 + %16 = load i32, ptr %i11, align 4 + %add21 = add i32 %16, 1 + store i32 %add21, ptr %i11, align 4 + br label %loop.cond12 + +loop.exit22: ; preds = %loop.cond12 + store i8 0, ptr %x, align 1 + %17 = load i8, ptr %x, align 1 + store i8 %17, ptr %switch23, align 1 + br label %switch.entry24 + +switch.entry24: ; preds = %loop.exit22 + %18 = load i8, ptr %switch23, align 1 + %19 = trunc i8 %18 to i1 + %eq25 = icmp eq i1 true, %19 + br i1 %eq25, label %switch.case26, label %next_if27 + +switch.case26: ; preds = %switch.entry24 + call void (ptr, ...) @printf(ptr @.str.8) + br label %switch.exit31 + +next_if27: ; preds = %switch.entry24 + %eq28 = icmp eq i1 false, %19 + br i1 %eq28, label %switch.case29, label %next_if30 + +switch.case29: ; preds = %next_if27 + call void (ptr, ...) @printf(ptr @.str.9) + br label %switch.exit31 + +next_if30: ; preds = %next_if27 + br label %switch.exit31 + +switch.exit31: ; preds = %next_if30, %switch.case29, %switch.case26 + ret void +} + +; Function Attrs: nounwind +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} + +attributes #0 = { nounwind } diff --git a/test/test_suite2/statements/return_stmt.c3 b/test/test_suite2/statements/return_stmt.c3 new file mode 100644 index 000000000..51da39f94 --- /dev/null +++ b/test/test_suite2/statements/return_stmt.c3 @@ -0,0 +1,11 @@ +fn void testNoReturn() +{ + int i = 0; + i = -i; +} + +fn int testReturn() +{ + int i = 0; + return i; +} \ No newline at end of file diff --git a/test/test_suite2/statements/return_switch.c3t b/test/test_suite2/statements/return_switch.c3t new file mode 100644 index 000000000..4b8295f83 --- /dev/null +++ b/test/test_suite2/statements/return_switch.c3t @@ -0,0 +1,36 @@ +fn int testReturnSwitch() +{ + int i = 0; + switch (i) + { + case 0: + case 3: + case 1: + return 2; + case 2: + return 3; + default: + return 4; + } +} + +// #expect: return_switch.ll + +switch.entry: + %1 = load i32, ptr %switch + switch i32 %1, label %switch.default [ + i32 0, label %switch.case + i32 3, label %switch.case + i32 1, label %switch.case + i32 2, label %switch.case1 + ] + +switch.case: + ret i32 2 + +switch.case1: + ret i32 3 + +switch.default: + ret i32 4 +} \ No newline at end of file diff --git a/test/test_suite2/statements/return_with_other_at_end.c3 b/test/test_suite2/statements/return_with_other_at_end.c3 new file mode 100644 index 000000000..09c6384e6 --- /dev/null +++ b/test/test_suite2/statements/return_with_other_at_end.c3 @@ -0,0 +1,7 @@ +fn int testReturnWithOtherAtEnd() +{ + int i = 0; + return i; + if (i == 10) i++; + i = i + 2; +} diff --git a/test/test_suite2/statements/simple_do.c3t b/test/test_suite2/statements/simple_do.c3t new file mode 100644 index 000000000..87dc21d76 --- /dev/null +++ b/test/test_suite2/statements/simple_do.c3t @@ -0,0 +1,113 @@ +// #target: macos-x64 + +module foo; +fn int test() +{ + static int x = 0; + return 1 + x++; +} + +extern fn void printf(char*, ...); + +fn void main() +{ + int i = 10; + do + { + printf("%d\n", test()); + if (i > 100) break; + } while (i-- > 0); + i = 1; + do + { + printf("%d, %d\n", i, test()); + if (i % 3 == 0) break; + } while (i++ < 100); +} + +/* #expect: foo.ll + +source_filename = "foo" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +@test.x = internal unnamed_addr global i32 0, align 4 +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@.str.1 = private unnamed_addr constant [8 x i8] c"%d, %d\0A\00", align 1 + +; Function Attrs: nounwind +define i32 @foo.test() #0 { +entry: + %0 = load i32, ptr @test.x, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr @test.x, align 4 + %add1 = add i32 1, %0 + ret i32 %add1 +} + +; Function Attrs: nounwind +declare void @printf(ptr, ...) #0 + +; Function Attrs: nounwind +define void @foo.main() #0 { +entry: + %i = alloca i32, align 4 + store i32 10, ptr %i, align 4 + br label %loop.body + +loop.cond: ; preds = %if.exit + %0 = load i32, ptr %i, align 4 + %sub = sub i32 %0, 1 + store i32 %sub, ptr %i, align 4 + %gt = icmp sgt i32 %0, 0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond, %entry + %1 = call i32 @foo.test() + call void (ptr, ...) @printf(ptr @.str, i32 %1) + %2 = load i32, ptr %i, align 4 + %gt1 = icmp sgt i32 %2, 100 + br i1 %gt1, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + br label %loop.exit + +if.exit: ; preds = %loop.body + br label %loop.cond + +loop.exit: ; preds = %if.then, %loop.cond + store i32 1, ptr %i, align 4 + br label %loop.body3 + +loop.cond2: ; preds = %if.exit5 + %3 = load i32, ptr %i, align 4 + %add = add i32 %3, 1 + store i32 %add, ptr %i, align 4 + %lt = icmp slt i32 %3, 100 + br i1 %lt, label %loop.body3, label %loop.exit6 + +loop.body3: ; preds = %loop.cond2, %loop.exit + %4 = load i32, ptr %i, align 4 + %5 = call i32 @foo.test() + call void (ptr, ...) @printf(ptr @.str.1, i32 %4, i32 %5) + %6 = load i32, ptr %i, align 4 + %smod = srem i32 %6, 3 + %eq = icmp eq i32 %smod, 0 + br i1 %eq, label %if.then4, label %if.exit5 + +if.then4: ; preds = %loop.body3 + br label %loop.exit6 + +if.exit5: ; preds = %loop.body3 + br label %loop.cond2 + +loop.exit6: ; preds = %if.then4, %loop.cond2 + ret void +} + +; Function Attrs: nounwind +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} diff --git a/test/test_suite2/statements/switch_error_range.c3 b/test/test_suite2/statements/switch_error_range.c3 new file mode 100644 index 000000000..fe39cce9d --- /dev/null +++ b/test/test_suite2/statements/switch_error_range.c3 @@ -0,0 +1,12 @@ +module foo; + +fn void test() +{ + int i; + switch (i) + { + case 15..13: // #error: The range is not valid because the first value (15) is greater than the second (13) + i++; + return; + } +} \ No newline at end of file diff --git a/test/test_suite2/statements/switch_errors.c3 b/test/test_suite2/statements/switch_errors.c3 new file mode 100644 index 000000000..995dcd023 --- /dev/null +++ b/test/test_suite2/statements/switch_errors.c3 @@ -0,0 +1,160 @@ + +enum Foo +{ + A, B +} + +enum Bar +{ + B +} + +fn void test_other_enum() +{ + Foo f = A; + switch (f) + { + case Foo.A: + break; + case B: + break; + case Bar.B: // #error: 'Bar' into 'Foo' + break; + } +} + +fn void test_check_nums() +{ + Foo f = A; + switch (f) + { + case (Foo)(1): + break; + case (Foo)(0): + break; + } +} + +fn void test_scope(int i) +{ + switch (i) + { + case 1: + int a = 0; + break; + case 2: + test_scope(a + 1); // #error: 'a' could not be found, did you spell it right + } +} + +fn void test_duplicate_case(int i) +{ + switch (i) + { + case 1: + break; + case 2: + break; + case 1: // #error: same case value appears + break; + } +} + +fn void test_duplicate_case2(Foo i) +{ + switch (i) + { + case A: + break; + case (Foo)(1): + break; + case A: // #error: same case value appears + break; + } +} + +fn void test_duplicate_case3(Foo i) +{ + switch (i) + { + case A: + break; + case (Foo)(0): // #error: same case value appears + break; + } +} + +enum Baz +{ + A, B, C, D +} + +fn void test_missing_all_cases(Baz x) +{ + switch (x) // -error: 4 enumeration values not handled in switch: A, B, C, ... + { + } +} + +fn void test_missing_some_cases(Baz x) +{ + switch (x) // -error: 4 enumeration B, C and D not handled in switch + { + case A: + break; + } +} + +fn void test_missing_some_cases2(Baz x) +{ + switch (x) // -error: 4 enumeration B and D not handled in switch + { + case C: + case A: + break; + } +} + +fn void test_missing_some_cases3(Baz x) +{ + switch (x) // -error: 4 enumeration B and D not handled in switch + { + case B: + case C: + case A: + break; + } +} + +fn void test_missing_no_cases(Baz x) +{ + switch (x) + { + default: + break; + } +} + +fault MathError +{ + DIVISION_BY_ZERO +} + +// Rethrowing an error uses "!!" suffix +fn void! testMayError() +{ +} + +fn void main() +{ + // Handle the error + switch (catch err = testMayError()) // #error: Catch unwrapping is only allowed + { + case MathError.DIVISION_BY_ZERO: + libc::printf("Division by zero\n"); + return; + default: + libc::printf("Unexpected error!"); + return; + } +} \ No newline at end of file diff --git a/test/test_suite2/statements/various_switching.c3t b/test/test_suite2/statements/various_switching.c3t new file mode 100644 index 000000000..4378e0e54 --- /dev/null +++ b/test/test_suite2/statements/various_switching.c3t @@ -0,0 +1,57 @@ +module mymodule; + +extern fn void printf(char *, ...); + +fault HelloErr +{ + FOO, +} +fault ByeErr +{ + BAR, + BAZ +} + +fn void test() +{ + int! x = ByeErr.BAR!; + + typeid z = int.typeid; + if (catch err = x) + { + case HelloErr.FOO: + printf("Hello\n"); + case ByeErr.BAR: + printf("Bye\n"); + default: + printf("Noerrmatch\n"); + } + switch (z) + { + case int: + printf("Was int!\n"); + case bool: + nextcase double; + case double: + nextcase; + default: + printf("Wasn't int :(\n"); + } + int a = 1; + int b = 2; + int zy = b + a; + switch (zy) + { + case a: + printf("Got a\n"); + case b: + printf("Got b\n"); + default: + printf("None of the above\n"); + } +} +fn void main() +{ + test(); + printf("Hello!\n"); +} diff --git a/test/test_suite2/statements/while_statement_placement.c3 b/test/test_suite2/statements/while_statement_placement.c3 new file mode 100644 index 000000000..66473b6eb --- /dev/null +++ b/test/test_suite2/statements/while_statement_placement.c3 @@ -0,0 +1,11 @@ +fn void test1() +{ + int a; + while (1) a++; + while (1) + { + a++; + } + while (1) + a++; // #error: must be placed on the same line +} \ No newline at end of file diff --git a/test/test_suite2/statements/while_switch.c3t b/test/test_suite2/statements/while_switch.c3t new file mode 100644 index 000000000..0167e2c3b --- /dev/null +++ b/test/test_suite2/statements/while_switch.c3t @@ -0,0 +1,92 @@ +// #target: macos-x64 +module test; + +extern fn int printf(char*, ...); +extern fn int foo(); + +fn int main() +{ + while (foo()) + { + switch (foo()) + { + case 0: + case 1: + case 2: + case 3: + printf("3"); + nextcase; + case 4: + printf("4"); + nextcase; + case 5: + case 6: + default: + break; + } + } + return 0; +} + +/* #expect: test.ll + +source_filename = "test" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +@.str = private unnamed_addr constant [2 x i8] c"3\00", align 1 +@.str.1 = private unnamed_addr constant [2 x i8] c"4\00", align 1 + +; Function Attrs: nounwind +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: nounwind +declare i32 @foo() #0 + +; Function Attrs: nounwind +define i32 @main() #0 { +entry: + %switch = alloca i32, align 4 + br label %loop.cond + +loop.cond: ; preds = %switch.exit, %entry + %0 = call i32 @foo() + %intbool = icmp ne i32 %0, 0 + br i1 %intbool, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = call i32 @foo() + store i32 %1, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %loop.body + %2 = load i32, ptr %switch, align 4 + switch i32 %2, label %switch.default [ + i32 0, label %switch.case + i32 1, label %switch.case + i32 2, label %switch.case + i32 3, label %switch.case + i32 4, label %switch.case1 + i32 5, label %switch.default + i32 6, label %switch.default + ] + +switch.case: ; preds = %switch.entry, %switch.entry, %switch.entry, %switch.entry + %3 = call i32 (ptr, ...) @printf(ptr @.str) + br label %switch.case1 + +switch.case1: ; preds = %switch.entry, %switch.case + %4 = call i32 (ptr, ...) @printf(ptr @.str.1) + br label %switch.default + +switch.default: ; preds = %switch.entry, %switch.entry, %switch.case1, %switch.entry + br label %switch.exit + +switch.exit: ; preds = %switch.default + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i32 0 +} + +attributes #0 = { nounwind } \ No newline at end of file diff --git a/test/test_suite2/strings/literal_errors.c3 b/test/test_suite2/strings/literal_errors.c3 new file mode 100644 index 000000000..805772c4a --- /dev/null +++ b/test/test_suite2/strings/literal_errors.c3 @@ -0,0 +1,22 @@ +// #target: macos-x64 + +char bar = '\xaf'; +char bar = '\x0F'; + +char bar = '\xgh'; // #error: Expected a two character + +char baz = '\ueeof'; // #error: Expected a four char +char eofk = '\u233'; // #error: Expected a four char + +char zab = '\Uaokdokok'; // #error: Expected an eight +char zab = '\Uaokdooekfoekfekfkeofkekok'; // #error: Expected an eight +char eofkq = '\UaUfko'; // #error: Expected an eight + +char x1 = '\u0023a'; // #error: Character literals with '\u' can only contain one character +char x2 = '\U00000023a'; // #error: Character literals with '\U' can only contain one character + +char x = 'äö'; // #error: may only contain one character +char feokf = '\9'; // #error: Invalid escape sequence '\9' +char fje = '123456789012345678'; // #error: The character literal exceeds 16 characters. + +char foekfe = ''; // #error: The character literal was empty \ No newline at end of file diff --git a/test/test_suite2/strings/literal_hex_ok.c3 b/test/test_suite2/strings/literal_hex_ok.c3 new file mode 100644 index 000000000..943edca35 --- /dev/null +++ b/test/test_suite2/strings/literal_hex_ok.c3 @@ -0,0 +1,3 @@ +char bar1 = '\xaf'; +ichar bar2 = '\x0F'; +ushort bar4 = '\u0FaF'; diff --git a/test/test_suite2/strings/literal_to_subarray.c3t b/test/test_suite2/strings/literal_to_subarray.c3t new file mode 100644 index 000000000..77580f172 --- /dev/null +++ b/test/test_suite2/strings/literal_to_subarray.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 + +char[] y = "hello"; + +fn void test() +{ + char[] x = "world"; +} + +/* #expect: literal_to_subarray.ll + +%"char[]" = type { ptr, i64 } + +@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@literal_to_subarray.y = local_unnamed_addr global %"char[]" { ptr @.str, i64 5 }, align 8 +@.str.1 = private unnamed_addr constant [6 x i8] c"world\00", align 1 + +; Function Attrs: nounwind +define void @literal_to_subarray.test() #0 { +entry: + %x = alloca %"char[]", align 8 + store %"char[]" { ptr @.str.1, i64 5 }, ptr %x, align 8 + ret void +} diff --git a/test/test_suite2/strings/multiline_strings.c3t b/test/test_suite2/strings/multiline_strings.c3t new file mode 100644 index 000000000..5b087a023 --- /dev/null +++ b/test/test_suite2/strings/multiline_strings.c3t @@ -0,0 +1,18 @@ +// #target: macos-x64 + +// This will depend on platform source file line endings +char *message2 = ` + ``oh`` superman + where are you now? +`; + +char *message3 = "Hfo\u0044ke"; +char *message4 = "\x64\x6f\x63\x75\x6d\x65\x6e\x74"; + + +// #expect: multiline_strings.ll + + +@.str = private unnamed_addr constant [41 x i8] c"\0A `oh` superman\0A where are you now?\0A\00", align 1 +@.str.3 = private unnamed_addr constant [7 x i8] c"HfoDke\00", align 1 +@.str.4 = private unnamed_addr constant [9 x i8] c"document\00", align 1 \ No newline at end of file diff --git a/test/test_suite2/strings/string_escape.c3t b/test/test_suite2/strings/string_escape.c3t new file mode 100644 index 000000000..e926a940a --- /dev/null +++ b/test/test_suite2/strings/string_escape.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 +fn void main() +{ + char *s = "Hello\0 world!" " now"; +} + +/* #expect: string_escape.ll + +@.str = private unnamed_addr constant [18 x i8] c"Hello\00 world! now\00", align 1 + +define void @string_escape.main() #0 { +entry: + %s = alloca ptr, align 8 + store ptr @.str, ptr %s, align 8 + ret void +} + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @string_escape.main() + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite2/strings/string_len.c3t b/test/test_suite2/strings/string_len.c3t new file mode 100644 index 000000000..8d76b2898 --- /dev/null +++ b/test/test_suite2/strings/string_len.c3t @@ -0,0 +1,7 @@ +// #target: macos-x64 + +int i = "123".len; + +/* #expect: string_len.ll + +@string_len.i = local_unnamed_addr global i32 3, align 4 \ No newline at end of file diff --git a/test/test_suite2/strings/string_to_array.c3t b/test/test_suite2/strings/string_to_array.c3t new file mode 100644 index 000000000..bc0f90b5a --- /dev/null +++ b/test/test_suite2/strings/string_to_array.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module foo; + +fn int main() +{ + char[2] x = "ab"; + char[*] y = "abc"; + return 0; +} + +/* #expect: foo.ll + +@.str = private unnamed_addr constant [3 x i8] c"ab\00", align 1 +@.str.1 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 + +define i32 @main() #0 { +entry: + %x = alloca [2 x i8], align 1 + %y = alloca [3 x i8], align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %x, ptr align 1 @.str, i32 2, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 @.str.1, i32 3, i1 false) + ret i32 0 +} diff --git a/test/test_suite2/struct/duplicate_member.c3 b/test/test_suite2/struct/duplicate_member.c3 new file mode 100644 index 000000000..345871af5 --- /dev/null +++ b/test/test_suite2/struct/duplicate_member.c3 @@ -0,0 +1,69 @@ +// @warnings{no-unused} +module test; + +struct Aa +{ + int a; + int a; // #error: Duplicate member name 'a' +} + +struct Bb +{ + int a; + struct a // #error: Duplicate member name 'a' + { + int b; + } +} + +union Cc +{ + int a; + int a; // #error: Duplicate member name 'a' + + struct b + { + int c; + int c; // #error: Duplicate member name 'c' + } +} + +struct Dd +{ + int b; + int a; + struct + { + union + { + short a; // #error: Duplicate member name 'a' + int b; // #error: Duplicate member name 'b' + } + } +} + +union Ee +{ + int a; + struct + { + short a; // #error: Duplicate member name 'a' + } +} + +struct Ff +{ + struct + { + int a; + } + struct b + { + int a; + } + union + { + int a; // #error: Duplicate member name 'a' + } +} + diff --git a/test/test_suite2/struct/flex_array_struct_err.c3 b/test/test_suite2/struct/flex_array_struct_err.c3 new file mode 100644 index 000000000..59faccf3b --- /dev/null +++ b/test/test_suite2/struct/flex_array_struct_err.c3 @@ -0,0 +1,31 @@ +struct Foo +{ + int x; + int[*] y; // #error: flexible array member must be the last element + int z; +} + +struct Bar +{ + int[*] y; // #error: flexible array member cannot be the only element +} + +struct Baz +{ + int y; + int[*] z; +} + +struct BazContainerOk +{ + int z; + Baz c; +} + +struct BazContainer +{ + Baz c; // #error: A struct member with a flexible array must be the last element. + int y; +} + +Baz[5] ab; // #error: Arrays of structs with flexible array members is not allowed. \ No newline at end of file diff --git a/test/test_suite2/struct/func_return_struct.c3 b/test/test_suite2/struct/func_return_struct.c3 new file mode 100644 index 000000000..66ae003b3 --- /dev/null +++ b/test/test_suite2/struct/func_return_struct.c3 @@ -0,0 +1,12 @@ +struct Test +{ + int i; + short s1, s2; +} + +extern fn Test func_returning_struct(); + +fn void loop() +{ + func_returning_struct(); +} diff --git a/test/test_suite2/struct/member_access.c3 b/test/test_suite2/struct/member_access.c3 new file mode 100644 index 000000000..c434fef35 --- /dev/null +++ b/test/test_suite2/struct/member_access.c3 @@ -0,0 +1,87 @@ +module test; + + +struct Multi +{ + int a, b, c; +} + +struct Point +{ + int a; + struct bb + { + int b; + } + struct + { + int b; + int c; + struct + { + Point* p; + } + } + union + { + int d; + short e; + } + union uu { + int d; + ushort e; + } +} + + +fn void tester() +{ + Multi m; + m.a = 1; + Point p; + p.a = 1; + p.bb.b = 2; + p.b = 3; + p.c = 4; + p.p = null; + p.d = 5; + p.e = 6; + p.uu.d = 7; + p.uu.e = 8; + Point *p2 = &p; + p2.bb.b = 3; + p = { .a = 1, .bb.b = 3, .e = 2 }; + + Point* pp = &p; + pp.a = 20; +} + +struct Aa1 +{ + struct bb + { + int b; + } + struct + { + int c; + } +} + +fn void test_conversion_struct() +{ + Aa1 a1; + int aa = a1.bb; // #error: 'bb' into 'int' +} + +struct Struct +{ + int a; +} + +fn void myfunc() +{ + Struct s; + s.b = 10; // #error: There is no field or method 'Struct.b' +} + diff --git a/test/test_suite2/struct/member_expr.c3 b/test/test_suite2/struct/member_expr.c3 new file mode 100644 index 000000000..77782deda --- /dev/null +++ b/test/test_suite2/struct/member_expr.c3 @@ -0,0 +1,31 @@ + +define Func = fn int(int); + +define Func2 = fn int(Foo*, int); + +struct Foo +{ + int a; + Func callback; +} + +fn int Foo.func2(Foo* f, int i) +{ + return f.a + i; +} + +fn void test_unknown_member() +{ + int a = Foo.b; // #error: No method or inner struct/union 'Foo.b' found. +} + + +fn void test_nonstatic_stuct_func1() +{ + Func2 a = &Foo.func2; +} + +fn void test_nonstatic_stuct_func2() +{ + int b = Foo.func2(null, 2); +} diff --git a/test/test_suite2/struct/recursive_structs.c3 b/test/test_suite2/struct/recursive_structs.c3 new file mode 100644 index 000000000..19dbbf06a --- /dev/null +++ b/test/test_suite2/struct/recursive_structs.c3 @@ -0,0 +1,25 @@ +struct Test1 +{ + Test1 *x; +} + +struct Test2 +{ + Test2[] y; +} + +struct Test3 // #error: Recursive definition +{ + Test3[4] z; +} + +struct Test4 +{ + Test4[3]* w; +} + + +struct Test5 +{ + Test5[3][] w; +} diff --git a/test/test_suite2/struct/simple_struct.c3t b/test/test_suite2/struct/simple_struct.c3t new file mode 100644 index 000000000..07bf821fe --- /dev/null +++ b/test/test_suite2/struct/simple_struct.c3t @@ -0,0 +1,14 @@ +module test; + +private Foo a; + +struct Foo +{ + int x; + double a; +} + +// #expect: test.ll + +%Foo = type { i32, double } +@test.a = protected unnamed_addr global %Foo zeroinitializer, align 8 \ No newline at end of file diff --git a/test/test_suite2/struct/struct_as_value.c3t b/test/test_suite2/struct/struct_as_value.c3t new file mode 100644 index 000000000..310b9a506 --- /dev/null +++ b/test/test_suite2/struct/struct_as_value.c3t @@ -0,0 +1,48 @@ +// #target: macos-x64 +module test; + +struct Event +{ + int op; +} + +fn Event test(int x) +{ + Event foo = { 1 }; + Event bar = { 2 }; + return x ? foo : bar; +} + +/* #expect: test.ll + +%Event = type { i32 } + +@.typeid.test.Event = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8 +@.__const = private unnamed_addr constant %Event { i32 1 }, align 4 +@.__const.1 = private unnamed_addr constant %Event { i32 2 }, align 4 + +define i32 @test.test(i32 %0) #0 { +entry: + %foo = alloca %Event, align 4 + %bar = alloca %Event, align 4 + %taddr = alloca %Event, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %foo, ptr align 4 @.__const, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %bar, ptr align 4 @.__const.1, i32 4, i1 false) + %intbool = icmp ne i32 %0, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %1 = load %Event, ptr %foo, align 4 + br label %cond.phi + +cond.rhs: ; preds = %entry + %2 = load %Event, ptr %bar, align 4 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi %Event [ %1, %cond.lhs ], [ %2, %cond.rhs ] + store %Event %val, ptr %taddr, align 4 + %3 = getelementptr inbounds %Event, ptr %taddr, i32 0, i32 0 + %4 = load i32, ptr %3, align 4 + ret i32 %4 +} \ No newline at end of file diff --git a/test/test_suite2/struct/struct_as_value_aarch64.c3t b/test/test_suite2/struct/struct_as_value_aarch64.c3t new file mode 100644 index 000000000..b17098766 --- /dev/null +++ b/test/test_suite2/struct/struct_as_value_aarch64.c3t @@ -0,0 +1,42 @@ +// #target: linux-aarch64 +module test; + +struct Event +{ + int op; +} + +fn Event test(int x) +{ + Event foo = { 1 }; + Event bar = { 2 }; + return x ? foo : bar; +} + +/* #expect: test.ll + +define i32 @test.test(i32 %0) #0 { +entry: + %foo = alloca %Event, align 4 + %bar = alloca %Event, align 4 + %taddr = alloca %Event, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %foo, ptr align 4 @.__const, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %bar, ptr align 4 @.__const.1, i32 4, i1 false) + %intbool = icmp ne i32 %0, 0 + br i1 %intbool, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %1 = load %Event, ptr %foo, align 4 + br label %cond.phi + +cond.rhs: ; preds = %entry + %2 = load %Event, ptr %bar, align 4 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi %Event [ %1, %cond.lhs ], [ %2, %cond.rhs ] + store %Event %val, ptr %taddr, align 4 + %3 = getelementptr inbounds %Event, ptr %taddr, i32 0, i32 0 + %4 = load i32, ptr %3, align 4 + ret i32 %4 +} diff --git a/test/test_suite2/struct/struct_codegen.c3t b/test/test_suite2/struct/struct_codegen.c3t new file mode 100644 index 000000000..c77564366 --- /dev/null +++ b/test/test_suite2/struct/struct_codegen.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +module test; + +struct Point +{ + int x; + int y; +} + +fn void test1() +{ + Point p = { 5, 6 }; +} + +/* #expect: test.ll + +%Point = type { i32, i32 } + +@.typeid.test.Point = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@.__const = private unnamed_addr constant %Point { i32 5, i32 6 }, align 4 + +define void @test.test1() #0 { +entry: + %p = alloca %Point, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %p, ptr align 4 @.__const, i32 8, i1 false) + ret void +} diff --git a/test/test_suite2/struct/struct_codegen_empty.c3t b/test/test_suite2/struct/struct_codegen_empty.c3t new file mode 100644 index 000000000..e2ccf101d --- /dev/null +++ b/test/test_suite2/struct/struct_codegen_empty.c3t @@ -0,0 +1,39 @@ +// #target: macos-x64 +struct StructA +{ + int a; +} + +struct StructB +{ + struct b + { + int a; + } +} + +fn void test() +{ + StructA a = {}; + StructA a2; + StructB b = {}; + StructB b2; + StructB b3 = { .b = { } }; +} + +/* #expect: struct_codegen_empty.ll + + define void @struct_codegen_empty.test() #0 { + entry: + %a = alloca %StructA, align 4 + %a2 = alloca %StructA, align 4 + %b = alloca %StructB, align 4 + %b2 = alloca %StructB, align 4 + %b3 = alloca %StructB, align 4 + store i32 0, ptr %a, align 4 + store i32 0, ptr %a2, align 4 + store i32 0, ptr %b, align 4 + store i32 0, ptr %b2, align 4 + store i32 0, ptr %b3, align 4 + ret void + } \ No newline at end of file diff --git a/test/test_suite2/struct/struct_codegen_fam.c3t b/test/test_suite2/struct/struct_codegen_fam.c3t new file mode 100644 index 000000000..fdca371e9 --- /dev/null +++ b/test/test_suite2/struct/struct_codegen_fam.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 +module foo; + +struct Bar +{ + struct + { + int y; + } + int ufe; + int[*] z; +} + + +fn void test(Bar b) +{ + b.z[1]; +} + +/* #expect: foo.ll + +%Bar = type { %anon, i32, [0 x i32] } +%anon = type { i32 } + +define void @foo.test(ptr byval(%Bar) align 8 %0) #0 { +entry: + %b = alloca %Bar, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 8 %0, i32 8, i1 false) + %1 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 2 + %2 = getelementptr inbounds [0 x i32], ptr %1, i64 0, i64 1 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/struct/struct_const_construct_simple.c3t b/test/test_suite2/struct/struct_const_construct_simple.c3t new file mode 100644 index 000000000..132bd74ff --- /dev/null +++ b/test/test_suite2/struct/struct_const_construct_simple.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module structo; + +struct Foo +{ + int foo; + long bar; +} + +private usize x = Foo.sizeof; + +private Foo foo1 = { 1, 2 }; +private Foo foo2 = { .foo = 2 }; +private Foo foo3 = { .bar = 3 }; +private Foo foo4 = { .bar = 4, .foo = 4, .bar = 1 }; +private Foo foo5 = {}; +private Foo foo6; +private const Foo FOO7 = { 1, 2 }; +private Foo foo8 = FOO7; + +/* #expect: structo.ll + +%Foo = type { i32, i64 } + +@.typeid.structo.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8 +@structo.x = protected unnamed_addr global i64 16, align 8 +@structo.foo1 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8 +@structo.foo2 = protected unnamed_addr global %Foo { i32 2, i64 0 }, align 8 +@structo.foo3 = protected unnamed_addr global %Foo { i32 0, i64 3 }, align 8 +@structo.foo4 = protected unnamed_addr global %Foo { i32 4, i64 1 }, align 8 +@structo.foo5 = protected unnamed_addr global %Foo zeroinitializer, align 8 +@structo.foo6 = protected unnamed_addr global %Foo zeroinitializer, align 8 +@structo.FOO7 = protected unnamed_addr constant %Foo { i32 1, i64 2 }, align 8 +@structo.foo8 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8 \ No newline at end of file diff --git a/test/test_suite2/struct/struct_pack_and_align.c3t b/test/test_suite2/struct/struct_pack_and_align.c3t new file mode 100644 index 000000000..d9110467e --- /dev/null +++ b/test/test_suite2/struct/struct_pack_and_align.c3t @@ -0,0 +1,101 @@ +// #target: macos-x64 + +module struct2; + +// <{ i64, i8, [3 x i8] }> +struct Foo1 @packed @align(4) +{ + long bar; + char foo; +} + +$assert(Foo1.sizeof == 12); +Foo1 foo1 = { 1, 2 }; + +// <{ i8, i64, [3 x i8] }> +struct Foo2 @packed @align(4) +{ + char foo; + long bar; +} + +$assert(Foo2.sizeof == 12); +Foo2 foo2 = { 1, 2 }; + +// <{ i8, i64, [7 x i8] }> +struct Foo3 @packed @align(8) +{ + char foo; + long bar; +} + +Foo3 foo3 = { 1, 2 }; +$assert(Foo3.sizeof == 16); + +// <{ i8, i64 }> +struct Foo4 @packed +{ + char foo; + long bar; +} + +$assert(Foo4.sizeof == 9); +Foo4 foo4 = { 1, 2 }; + +// { i32, [12 x i8], i8, [15 x i8] } +struct Foo5 +{ + int bar @align(16); + ichar foo @align(16); +} + +$assert(Foo5.sizeof == 32); +Foo5 foo5 = { 1, 2 }; + +fn int test5(ichar x) +{ + Foo5 y = { .foo = x }; + return y.foo + y.bar; +} + +// { i32, i16, i16 } +struct Foo6 @packed +{ + int a; + short b; + short c; +} + +$assert(Foo6.sizeof == 8); +Foo6 foo6 = { 1, 2, 3 }; + +/* #expect: struct2.ll + +%Foo1 = type <{ i64, i8, [3 x i8] }> +%Foo2 = type <{ i8, i64, [3 x i8] }> +%Foo3 = type <{ i8, i64, [7 x i8] }> +%Foo4 = type <{ i8, i64 }> +%Foo5 = type { i32, [12 x i8], i8, [15 x i8] } +%Foo6 = type { i32, i16, i16 } + +@struct2.foo1 = local_unnamed_addr global %Foo1 <{ i64 1, i8 2, [3 x i8] undef }>, align 4 +@struct2.foo2 = local_unnamed_addr global %Foo2 <{ i8 1, i64 2, [3 x i8] undef }>, align 4 +@struct2.foo3 = local_unnamed_addr global %Foo3 <{ i8 1, i64 2, [7 x i8] undef }>, align 8 +@struct2.foo4 = local_unnamed_addr global %Foo4 <{ i8 1, i64 2 }>, align 1 +@struct2.foo5 = local_unnamed_addr global %Foo5 { i32 1, [12 x i8] undef, i8 2, [15 x i8] undef }, align 16 +@struct2.foo6 = local_unnamed_addr global %Foo6 { i32 1, i16 2, i16 3 }, align 1 + +define i32 @struct2.test5(i8 signext %0) #0 { +entry: + %y = alloca %Foo5, align 16 + call void @llvm.memset.p0.i64(ptr align 16 %y, i8 0, i64 32, i1 false) + %1 = getelementptr inbounds %Foo5, ptr %y, i32 0, i32 2 + store i8 %0, ptr %1, align 16 + %2 = getelementptr inbounds %Foo5, ptr %y, i32 0, i32 2 + %3 = load i8, ptr %2, align 16 + %sisiext = sext i8 %3 to i32 + %4 = getelementptr inbounds %Foo5, ptr %y, i32 0, i32 0 + %5 = load i32, ptr %4, align 16 + %add = add i32 %sisiext, %5 + ret i32 %add +} \ No newline at end of file diff --git a/test/test_suite2/struct/struct_params.c3 b/test/test_suite2/struct/struct_params.c3 new file mode 100644 index 000000000..8a4bd2f69 --- /dev/null +++ b/test/test_suite2/struct/struct_params.c3 @@ -0,0 +1,27 @@ +module test; + +struct Foo +{ + char p; + short q; + char r; + int x; + short y, z; + int q2; +} + +extern fn int test(Foo, float); +extern fn int testE(char,short,char,int,int,float); + +fn void test3(Foo *x) +{ + x.q = 1; +} + +fn void test2(Foo y) +{ + testE(y.p, y.q, y.r, y.x, y.y, 0.1); + test(y, 0.1); + test2(y); + test3(&y); +} diff --git a/test/test_suite2/struct/zero_member.c3 b/test/test_suite2/struct/zero_member.c3 new file mode 100644 index 000000000..fb5c145ad --- /dev/null +++ b/test/test_suite2/struct/zero_member.c3 @@ -0,0 +1,7 @@ +define Foo = int[0]; + +struct Bar +{ + Foo x; // #error: Zero length arrays are not valid members. + int b; +} \ No newline at end of file diff --git a/test/test_suite2/subarrays/slice_comparison.c3t b/test/test_suite2/subarrays/slice_comparison.c3t new file mode 100644 index 000000000..017abab2c --- /dev/null +++ b/test/test_suite2/subarrays/slice_comparison.c3t @@ -0,0 +1,232 @@ +// #target: macos-x64 + +module mymodule; + +extern fn void printf(char *, ...); + +fn void main() +{ + + char[] y = "hodo"; + char[] z = "hodo"; + if (y == "hodo") + { + printf("This works\n"); + } + if (y == z) + { + printf("This works too\n"); + } + switch (y) + { + case "mixx": + printf("Wut\n"); + case "hodot": + printf("Nope\n"); + case "hodo": + printf("Winning!\n"); + default: + printf("Hodohell\n"); + } + +} + +/* #expect: mymodule.ll + + +define void @mymodule.main() #0 { +entry: + %y = alloca %"char[]", align 8 + %z = alloca %"char[]", align 8 + %cmp.idx = alloca i64, align 8 + %cmp.idx5 = alloca i64, align 8 + %switch = alloca %"char[]", align 8 + %cmp.idx18 = alloca i64, align 8 + %cmp.idx29 = alloca i64, align 8 + %cmp.idx42 = alloca i64, align 8 + store %"char[]" { ptr @.str, i64 4 }, ptr %y, align 8 + store %"char[]" { ptr @.str.1, i64 4 }, ptr %z, align 8 + %0 = load %"char[]", ptr %y, align 8 + %1 = extractvalue %"char[]" %0, 1 + %2 = extractvalue %"char[]" %0, 0 + %eq = icmp eq i64 %1, 4 + br i1 %eq, label %subarray_cmp_values, label %subarray_cmp_exit + +subarray_cmp_values: ; preds = %entry + store i64 0, ptr %cmp.idx, align 8 + br label %subarray_loop_start + +subarray_loop_start: ; preds = %subarray_loop_comparison, %subarray_cmp_values + %3 = load i64, ptr %cmp.idx, align 8 + %lt = icmp ult i64 %3, %1 + br i1 %lt, label %subarray_loop_comparison, label %subarray_cmp_exit + +subarray_loop_comparison: ; preds = %subarray_loop_start + %ptroffset = getelementptr inbounds i8, ptr %2, i64 %3 + %ptroffset1 = getelementptr inbounds i8, ptr @.str.2, i64 %3 + %4 = load i8, ptr %ptroffset, align 1 + %5 = load i8, ptr %ptroffset1, align 1 + %eq2 = icmp eq i8 %4, %5 + %6 = add i64 %3, 1 + store i64 %6, ptr %cmp.idx, align 8 + br i1 %eq2, label %subarray_loop_start, label %subarray_cmp_exit + +subarray_cmp_exit: ; preds = %subarray_loop_comparison, %subarray_loop_start, %entry + %subarray_cmp_phi = phi i1 [ true, %subarray_loop_start ], [ false, %entry ], [ false, %subarray_loop_comparison ] + br i1 %subarray_cmp_phi, label %if.then, label %if.exit + +if.then: ; preds = %subarray_cmp_exit + call void (ptr, ...) @printf(ptr @.str.3) + br label %if.exit + +if.exit: ; preds = %if.then, %subarray_cmp_exit + %7 = load %"char[]", ptr %y, align 8 + %8 = load %"char[]", ptr %z, align 8 + %9 = extractvalue %"char[]" %7, 1 + %10 = extractvalue %"char[]" %8, 1 + %11 = extractvalue %"char[]" %7, 0 + %12 = extractvalue %"char[]" %8, 0 + %eq3 = icmp eq i64 %9, %10 + br i1 %eq3, label %subarray_cmp_values4, label %subarray_cmp_exit12 + +subarray_cmp_values4: ; preds = %if.exit + store i64 0, ptr %cmp.idx5, align 8 + br label %subarray_loop_start6 + +subarray_loop_start6: ; preds = %subarray_loop_comparison8, %subarray_cmp_values4 + %13 = load i64, ptr %cmp.idx5, align 8 + %lt7 = icmp ult i64 %13, %9 + br i1 %lt7, label %subarray_loop_comparison8, label %subarray_cmp_exit12 + +subarray_loop_comparison8: ; preds = %subarray_loop_start6 + %ptroffset9 = getelementptr inbounds i8, ptr %11, i64 %13 + %ptroffset10 = getelementptr inbounds i8, ptr %12, i64 %13 + %14 = load i8, ptr %ptroffset9, align 1 + %15 = load i8, ptr %ptroffset10, align 1 + %eq11 = icmp eq i8 %14, %15 + %16 = add i64 %13, 1 + store i64 %16, ptr %cmp.idx5, align 8 + br i1 %eq11, label %subarray_loop_start6, label %subarray_cmp_exit12 + +subarray_cmp_exit12: ; preds = %subarray_loop_comparison8, %subarray_loop_start6, %if.exit + %subarray_cmp_phi13 = phi i1 [ true, %subarray_loop_start6 ], [ false, %if.exit ], [ false, %subarray_loop_comparison8 ] + br i1 %subarray_cmp_phi13, label %if.then14, label %if.exit15 + +if.then14: ; preds = %subarray_cmp_exit12 + call void (ptr, ...) @printf(ptr @.str.4) + br label %if.exit15 + +if.exit15: ; preds = %if.then14, %subarray_cmp_exit12 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %switch, ptr align 8 %y, i32 16, i1 false) + br label %switch.entry + +switch.entry: ; preds = %if.exit15 + %17 = load %"char[]", ptr %switch, align 8 + %18 = extractvalue %"char[]" %17, 1 + %19 = extractvalue %"char[]" %17, 0 + %eq16 = icmp eq i64 4, %18 + br i1 %eq16, label %subarray_cmp_values17, label %subarray_cmp_exit25 + +subarray_cmp_values17: ; preds = %switch.entry + store i64 0, ptr %cmp.idx18, align 8 + br label %subarray_loop_start19 + +subarray_loop_start19: ; preds = %subarray_loop_comparison21, %subarray_cmp_values17 + %20 = load i64, ptr %cmp.idx18, align 8 + %lt20 = icmp ult i64 %20, 4 + br i1 %lt20, label %subarray_loop_comparison21, label %subarray_cmp_exit25 + +subarray_loop_comparison21: ; preds = %subarray_loop_start19 + %ptroffset22 = getelementptr inbounds i8, ptr @.str.5, i64 %20 + %ptroffset23 = getelementptr inbounds i8, ptr %19, i64 %20 + %21 = load i8, ptr %ptroffset22, align 1 + %22 = load i8, ptr %ptroffset23, align 1 + %eq24 = icmp eq i8 %21, %22 + %23 = add i64 %20, 1 + store i64 %23, ptr %cmp.idx18, align 8 + br i1 %eq24, label %subarray_loop_start19, label %subarray_cmp_exit25 + +subarray_cmp_exit25: ; preds = %subarray_loop_comparison21, %subarray_loop_start19, %switch.entry + %subarray_cmp_phi26 = phi i1 [ true, %subarray_loop_start19 ], [ false, %switch.entry ], [ false, %subarray_loop_comparison21 ] + br i1 %subarray_cmp_phi26, label %switch.case, label %next_if + +switch.case: ; preds = %subarray_cmp_exit25 + call void (ptr, ...) @printf(ptr @.str.6) + br label %switch.exit + +next_if: ; preds = %subarray_cmp_exit25 + %24 = extractvalue %"char[]" %17, 1 + %25 = extractvalue %"char[]" %17, 0 + %eq27 = icmp eq i64 5, %24 + br i1 %eq27, label %subarray_cmp_values28, label %subarray_cmp_exit36 + +subarray_cmp_values28: ; preds = %next_if + store i64 0, ptr %cmp.idx29, align 8 + br label %subarray_loop_start30 + +subarray_loop_start30: ; preds = %subarray_loop_comparison32, %subarray_cmp_values28 + %26 = load i64, ptr %cmp.idx29, align 8 + %lt31 = icmp ult i64 %26, 5 + br i1 %lt31, label %subarray_loop_comparison32, label %subarray_cmp_exit36 + +subarray_loop_comparison32: ; preds = %subarray_loop_start30 + %ptroffset33 = getelementptr inbounds i8, ptr @.str.7, i64 %26 + %ptroffset34 = getelementptr inbounds i8, ptr %25, i64 %26 + %27 = load i8, ptr %ptroffset33, align 1 + %28 = load i8, ptr %ptroffset34, align 1 + %eq35 = icmp eq i8 %27, %28 + %29 = add i64 %26, 1 + store i64 %29, ptr %cmp.idx29, align 8 + br i1 %eq35, label %subarray_loop_start30, label %subarray_cmp_exit36 + +subarray_cmp_exit36: ; preds = %subarray_loop_comparison32, %subarray_loop_start30, %next_if + %subarray_cmp_phi37 = phi i1 [ true, %subarray_loop_start30 ], [ false, %next_if ], [ false, %subarray_loop_comparison32 ] + br i1 %subarray_cmp_phi37, label %switch.case38, label %next_if39 + +switch.case38: ; preds = %subarray_cmp_exit36 + call void (ptr, ...) @printf(ptr @.str.8) + br label %switch.exit + +next_if39: ; preds = %subarray_cmp_exit36 + %30 = extractvalue %"char[]" %17, 1 + %31 = extractvalue %"char[]" %17, 0 + %eq40 = icmp eq i64 4, %30 + br i1 %eq40, label %subarray_cmp_values41, label %subarray_cmp_exit49 + +subarray_cmp_values41: ; preds = %next_if39 + store i64 0, ptr %cmp.idx42, align 8 + br label %subarray_loop_start43 + +subarray_loop_start43: ; preds = %subarray_loop_comparison45, %subarray_cmp_values41 + %32 = load i64, ptr %cmp.idx42, align 8 + %lt44 = icmp ult i64 %32, 4 + br i1 %lt44, label %subarray_loop_comparison45, label %subarray_cmp_exit49 + +subarray_loop_comparison45: ; preds = %subarray_loop_start43 + %ptroffset46 = getelementptr inbounds i8, ptr @.str.9, i64 %32 + %ptroffset47 = getelementptr inbounds i8, ptr %31, i64 %32 + %33 = load i8, ptr %ptroffset46, align 1 + %34 = load i8, ptr %ptroffset47, align 1 + %eq48 = icmp eq i8 %33, %34 + %35 = add i64 %32, 1 + store i64 %35, ptr %cmp.idx42, align 8 + br i1 %eq48, label %subarray_loop_start43, label %subarray_cmp_exit49 + +subarray_cmp_exit49: ; preds = %subarray_loop_comparison45, %subarray_loop_start43, %next_if39 + %subarray_cmp_phi50 = phi i1 [ true, %subarray_loop_start43 ], [ false, %next_if39 ], [ false, %subarray_loop_comparison45 ] + br i1 %subarray_cmp_phi50, label %switch.case51, label %next_if52 + +switch.case51: ; preds = %subarray_cmp_exit49 + call void (ptr, ...) @printf(ptr @.str.10) + br label %switch.exit + +next_if52: ; preds = %subarray_cmp_exit49 + br label %switch.default + +switch.default: ; preds = %next_if52 + call void (ptr, ...) @printf(ptr @.str.11) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case51, %switch.case38, %switch.case + ret void +} diff --git a/test/test_suite2/subarrays/slice_negative_len.c3 b/test/test_suite2/subarrays/slice_negative_len.c3 new file mode 100644 index 000000000..3ce848262 --- /dev/null +++ b/test/test_suite2/subarrays/slice_negative_len.c3 @@ -0,0 +1,72 @@ +fn void test() +{ + int[3] x = { 1, 2, 3}; + int[] z = x[2..2]; + z = x[2..1]; // #error: Start index greater than end index. +} + +fn void test2() +{ + int[3] x = { 1, 2, 3}; + int[] z = x[^2..^2]; + z = x[^3..]; + z = x[^1..^2]; // #error: Start index greater than end index. +} + +fn void test3() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[..4]; // #error: Array end index out of bounds, was 4, exceeding array length 3. +} + +fn void test4() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[..^1]; + z = x[..^-1]; // #error: Negative numbers are not allowed when indexing from the end. +} + +fn void test5() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[..^4]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers. +} + +fn void test6() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[3..]; // #error: Array index out of bounds, was 3, exceeding max array index 2. +} + +fn void test7() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[-1..]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers. +} + +fn void test8() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[^4..]; // #error: Array index out of bounds, using a negative array index is only allowed with pointers. +} + +fn void test9() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[^0..]; // #error: Array index out of bounds, was 3, exceeding max array index 2. +} + +fn void test10() +{ + int* x = null; + x[-10..-3]; + int[] w = x[0..]; // #error: Omitting end index is not allowed for pointers. + int[] z = x[^2..]; // #error: Indexing from the end is not allowed for pointers. + int[] y = x[..^2]; // #error: Indexing from the end is not allowed for pointers. +} + +fn void test11() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[..^0]; // #error: Array end index out of bounds, was 3, exceeding array length 3 +} diff --git a/test/test_suite2/subarrays/slice_offset.c3t b/test/test_suite2/subarrays/slice_offset.c3t new file mode 100644 index 000000000..37c881979 --- /dev/null +++ b/test/test_suite2/subarrays/slice_offset.c3t @@ -0,0 +1,19 @@ +fn void test() +{ + int[3] x = { 1, 2, 3 }; + int[] y = x[1..2]; +} + +/* #expect: slice_offset.ll + +define void @slice_offset.test() #0 { +entry: + %x = alloca [3 x i32], align 4 + %y = alloca %"int[]", align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + %1 = insertvalue %"int[]" undef, ptr %0, 0 + %2 = insertvalue %"int[]" %1, i64 2, 1 + store %"int[]" %2, ptr %y, align 8 + ret void +} diff --git a/test/test_suite2/subarrays/slice_offset_neg_end.c3t b/test/test_suite2/subarrays/slice_offset_neg_end.c3t new file mode 100644 index 000000000..b7592bb09 --- /dev/null +++ b/test/test_suite2/subarrays/slice_offset_neg_end.c3t @@ -0,0 +1,20 @@ + +fn void test() +{ + int[3] x = { 1, 2, 3 }; + int[] y = x[1..^1]; +} + +/* #expect: slice_offset_neg_end.ll + +define void @slice_offset_neg_end.test() #0 { +entry: + %x = alloca [3 x i32], align 4 + %y = alloca %"int[]", align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + %1 = insertvalue %"int[]" undef, ptr %0, 0 + %2 = insertvalue %"int[]" %1, i64 2, 1 + store %"int[]" %2, ptr %y, align 8 + ret void +} diff --git a/test/test_suite2/subarrays/slice_offset_neg_start.c3t b/test/test_suite2/subarrays/slice_offset_neg_start.c3t new file mode 100644 index 000000000..cc03293be --- /dev/null +++ b/test/test_suite2/subarrays/slice_offset_neg_start.c3t @@ -0,0 +1,19 @@ +fn void test() +{ + int[3] x = { 1, 2, 3 }; + int[] y = x[^2..1]; +} + +/* #expect: slice_offset_neg_start.ll + +define void @slice_offset_neg_start.test() #0 { +entry: + %x = alloca [3 x i32], align 4 + %y = alloca %"int[]", align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 1 + %1 = insertvalue %"int[]" undef, ptr %0, 0 + %2 = insertvalue %"int[]" %1, i64 1, 1 + store %"int[]" %2, ptr %y, align 8 + ret void +} diff --git a/test/test_suite2/subarrays/slice_start.c3t b/test/test_suite2/subarrays/slice_start.c3t new file mode 100644 index 000000000..c81549952 --- /dev/null +++ b/test/test_suite2/subarrays/slice_start.c3t @@ -0,0 +1,19 @@ +fn void test() +{ + int[3] x = { 1, 2, 3 }; + int[] y = x[..]; +} + +/* #expect: slice_start.ll + +define void @slice_start.test() #0 { +entry: + %x = alloca [3 x i32], align 4 + %y = alloca %"int[]", align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %0 = getelementptr inbounds [3 x i32], ptr %x, i64 0, i64 0 + %1 = insertvalue %"int[]" undef, ptr %0, 0 + %2 = insertvalue %"int[]" %1, i64 3, 1 + store %"int[]" %2, ptr %y, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/subarrays/slice_syntax.c3 b/test/test_suite2/subarrays/slice_syntax.c3 new file mode 100644 index 000000000..e4f3f641c --- /dev/null +++ b/test/test_suite2/subarrays/slice_syntax.c3 @@ -0,0 +1,24 @@ +fn void test() +{ + int[6] feok2 = { 1, 8, 100, 293, 23982, 34}; + int[] feok = &feok2; + int[] flok = feok2[3..5]; + int[] flak = flok[1..2]; + flok = feok2[..5]; + flok = feok2[..^2]; + flok = feok2[..]; + flok = feok2[^3..]; + flok = feok2[^4..5]; + flok = feok2[2..^2]; + flok = feok2[^3..^1]; + flok = feok2[..]; + flak = flok[..6]; + flak = flok[..^2]; + flak = flok[..]; + flak = flok[^3..]; + flak = flok[^4..5]; + flak = flok[2..^2]; + flak = flok[^3..^1]; + int* p = null; + // TODO p[-1..20]; +} \ No newline at end of file diff --git a/test/test_suite2/subarrays/sub_array_init.c3 b/test/test_suite2/subarrays/sub_array_init.c3 new file mode 100644 index 000000000..4becdc105 --- /dev/null +++ b/test/test_suite2/subarrays/sub_array_init.c3 @@ -0,0 +1,7 @@ +fn void test2() +{ + int[2] a = { 1, 2 }; + + int[2] b = 30; // #error: 'int' into 'int[2]' + int[2] c = a; +} diff --git a/test/test_suite2/switch/failable_switch.c3 b/test/test_suite2/switch/failable_switch.c3 new file mode 100644 index 000000000..79cc80b4d --- /dev/null +++ b/test/test_suite2/switch/failable_switch.c3 @@ -0,0 +1,14 @@ +fault MyError +{ + FOO +} + +fn void test() +{ + int x = 0; + switch (x) + { + case MyError.FOO!: // #error: You cannot have a failable here + x = x + 1; + } +} \ No newline at end of file diff --git a/test/test_suite2/symbols/allow_local_shadowing.c3 b/test/test_suite2/symbols/allow_local_shadowing.c3 new file mode 100644 index 000000000..802eaf090 --- /dev/null +++ b/test/test_suite2/symbols/allow_local_shadowing.c3 @@ -0,0 +1,10 @@ +int foo; + +fn void x() +{ + double foo = 123; +} + +fn void y(int foo) +{ +} \ No newline at end of file diff --git a/test/test_suite2/symbols/shadow_struct.c3 b/test/test_suite2/symbols/shadow_struct.c3 new file mode 100644 index 000000000..72b36f698 --- /dev/null +++ b/test/test_suite2/symbols/shadow_struct.c3 @@ -0,0 +1,15 @@ +struct Foo +{ + Foo *x; + int y; +} + +define Foo = float; // #error: shadow a previous declaration + +enum Bar +{ + TEST1, + TEST2 +} + +define Bar = float; // #error: shadow a previous declaration \ No newline at end of file diff --git a/test/test_suite2/symbols/various.c3 b/test/test_suite2/symbols/various.c3 new file mode 100644 index 000000000..b6b381c6f --- /dev/null +++ b/test/test_suite2/symbols/various.c3 @@ -0,0 +1,189 @@ +module test; + +fn void test1() +{ + char a = 1; + int b = 2; + char c = b > a ? 1 : 0; +} + +fn void test2() +{ + char a = 1; + char b = 2; + char c = a + b; +} + +fn void test3() +{ + ichar a = 1; + int b = 2; + ichar c = a + b; // #error: 'int' to 'ichar' +} + +fn void test4() +{ + char a = 1; + char b = 2; + int c = a + b; +} + +fn void test5() +{ + char a = 1; + int b = 2; + int c = a + b; +} + + +fn void test6() +{ + char a = 1; + char b = 2; + char c = (b > a) ? 1 : 0 + a + b; +} + +fn void test7() +{ + int[100] array = { }; + int v = array[1]; +} + +define Number = int; + +fn void test8() +{ + Number a = 10; + ichar c = a; // #error: 'Number' (int) to 'ichar' +} + + +fn void test9() +{ + const char A = 1; + char b = A; + A = b; // #error: An assignable expression +} + +fn void test10() +{ + const char B = 1; + char* c = &B; + const A = 1; + char* b = &A; // #error: either type it or use && to take the reference to a temporary +} + +enum Enum : int +{ + A, + B, +} + +fn void test11() +{ + int a = Enum.A; + ichar b = Enum.B; // #error: 'Enum' to 'ichar' +} + +fn void test12() +{ + float f = 3.14; + ichar a = f; // #error: 'float' to 'ichar' +} + +fn void test13() +{ + int a = 1; + ichar b = a; // #error: 'int' to 'ichar' +} + +fn void test14() +{ + char a = 1; + ichar b = a; +} + +fn void test15() +{ + float f = 3.14; + ichar c = 1; + ichar* a = &f; // #error: 'float*' to 'ichar*' + ichar* b = &c; +} + +fn void test16() +{ + float f = 3.14; + int i = 1; + + ichar c = 1 ? 'c' : 'd'; + ichar d = 1 ? 'c' : i; + ichar e = 1 ? i : 0; // #error: 'int' to 'ichar' + int g = 1 ? i : f; // #error: 'float' to 'int' + int a = f ? 1 : 0; +} + +fn void test17() +{ + int a = "test"; // #error: 'char[4]*' into 'int' +} + +fn void test18() +{ + char b = 1; + int a = b; +} + +fn void test19() +{ + uint a = 1; + int b = a; +} + +/* +const i32 Num = 200; + +fn void test1() { + i8 a = test.Num; // @error{constant value 200 out-of-bounds for type 'i8', range [-128, 127]} +}*/ + +fn void test21() +{ + int a = 1; + uint b = a; +} + +fn void foo() {} + +fn void test22() +{ + ichar a = foo(); // #error: 'void' into 'ichar' + short b = foo(); // #error: 'void' into 'short' + int c = foo(); // #error: 'void' into 'int' + long d = foo(); // #error: 'void' into 'long' + char e = foo(); // #error: 'void' into 'char' + ushort f = foo(); // #error: 'void' into 'ushort' + uint g = foo(); // #error: 'void' into 'uint' + ulong h = foo(); // #error: 'void' into 'ulong' + bool i = foo(); // #error: 'void' into 'bool' +} + + +int num = 10; + +fn void test23() +{ + int a = num; + int b = test::num; + char c = test::num; // #error: 'int' to 'char' +} + +int[2][3] b123; + +fn void test24() +{ + int a = b123; // #error: 'int[2][3]' into 'int' +} + + + diff --git a/test/test_suite2/types/enum_illegal_type.c3 b/test/test_suite2/types/enum_illegal_type.c3 new file mode 100644 index 000000000..0c2a2610a --- /dev/null +++ b/test/test_suite2/types/enum_illegal_type.c3 @@ -0,0 +1,9 @@ +enum EnumTestErrorType : float // #error: must be an integer type not 'float' +{ + VALUE_BOOM +} + +enum EnumWithErrorType2 : int* // #error: must be an integer type not 'int*' +{ + TEST +} \ No newline at end of file diff --git a/test/test_suite2/types/enum_implicit_overflow.c3 b/test/test_suite2/types/enum_implicit_overflow.c3 new file mode 100644 index 000000000..aa64a25ae --- /dev/null +++ b/test/test_suite2/types/enum_implicit_overflow.c3 @@ -0,0 +1,136 @@ +enum Foo : ichar +{ + MY_VAL0, + MY_VAL1, + MY_VAL2, + MY_VAL3, + MY_VAL4, + MY_VAL5, + MY_VAL6, + MY_VAL7, + MY_VAL8, + MY_VAL9, + MY_VAL10, + MY_VAL11, + MY_VAL12, + MY_VAL13, + MY_VAL14, + MY_VAL15, + MY_VAL16, + MY_VAL17, + MY_VAL18, + MY_VAL19, + MY_VAL20, + MY_VAL21, + MY_VAL22, + MY_VAL23, + MY_VAL24, + MY_VAL25, + MY_VAL26, + MY_VAL27, + MY_VAL28, + MY_VAL29, + MY_VAL30, + MY_VAL31, + MY_VAL32, + MY_VAL33, + MY_VAL34, + MY_VAL35, + MY_VAL36, + MY_VAL37, + MY_VAL38, + MY_VAL39, + MY_VAL40, + MY_VAL41, + MY_VAL42, + MY_VAL43, + MY_VAL44, + MY_VAL45, + MY_VAL46, + MY_VAL47, + MY_VAL48, + MY_VAL49, + MY_VAL50, + MY_VAL51, + MY_VAL52, + MY_VAL53, + MY_VAL54, + MY_VAL55, + MY_VAL56, + MY_VAL57, + MY_VAL58, + MY_VAL59, + MY_VAL60, + MY_VAL61, + MY_VAL62, + MY_VAL63, + MY_VAL64, + MY_VAL65, + MY_VAL66, + MY_VAL67, + MY_VAL68, + MY_VAL69, + MY_VAL70, + MY_VAL71, + MY_VAL72, + MY_VAL73, + MY_VAL74, + MY_VAL75, + MY_VAL76, + MY_VAL77, + MY_VAL78, + MY_VAL79, + MY_VAL80, + MY_VAL81, + MY_VAL82, + MY_VAL83, + MY_VAL84, + MY_VAL85, + MY_VAL86, + MY_VAL87, + MY_VAL88, + MY_VAL89, + MY_VAL90, + MY_VAL91, + MY_VAL92, + MY_VAL93, + MY_VAL94, + MY_VAL95, + MY_VAL96, + MY_VAL97, + MY_VAL98, + MY_VAL99, + MY_VAL100, + MY_VAL101, + MY_VAL102, + MY_VAL103, + MY_VAL104, + MY_VAL105, + MY_VAL106, + MY_VAL107, + MY_VAL108, + MY_VAL109, + MY_VAL110, + MY_VAL111, + MY_VAL112, + MY_VAL113, + MY_VAL114, + MY_VAL115, + MY_VAL116, + MY_VAL117, + MY_VAL118, + MY_VAL119, + MY_VAL120, + MY_VAL121, + MY_VAL122, + MY_VAL123, + MY_VAL124, + MY_VAL125, + MY_VAL126, + MY_VAL127, + MY_VAL128, // #error: The enum value would implicitly be 128 which does not fit in 'ichar' + MY_VAL129, + + + +} \ No newline at end of file diff --git a/test/test_suite2/types/enum_inference.c3 b/test/test_suite2/types/enum_inference.c3 new file mode 100644 index 000000000..6899a879e --- /dev/null +++ b/test/test_suite2/types/enum_inference.c3 @@ -0,0 +1,43 @@ + +enum Inf +{ + A, + B, + C +} + +enum Inf2 : char +{ + A, + B, + C, +} + +define BooInf = Inf; + + +fn void enumInferenceTest() +{ + Inf x = Inf.A; + x = BooInf.B; + x = A; + int x1 = 0; + bool y = x1 == x1; + Inf2 z = C; + if (z == Inf2.A) return; + if (z == 1) return; + z = (Inf2)(2); + switch (z) + { + case Inf2.A: + x1++; + return; + case B: + return; + case (Inf2)(2): + x1 += 1; + return; + default: + return; + } +} \ No newline at end of file diff --git a/test/test_suite2/types/enum_ok.c3 b/test/test_suite2/types/enum_ok.c3 new file mode 100644 index 000000000..1374947c8 --- /dev/null +++ b/test/test_suite2/types/enum_ok.c3 @@ -0,0 +1,35 @@ +enum EnumTest : long +{ + VALUE1, + VALUE2 +} + +define Frob = long; + +enum EnumTestAlias : Frob +{ + VALUE1, + VALUE2 +} + +enum EnumTestDefault +{ + VALUE, + VALUE2 +} + + +enum EnumWithErrorData2 : int (int bar, ) +{ + TEST // #error: Expected associated value +} + +enum EnumTestErrorType4 +{ +} + +enum EnumTest5 +{ + B, + C, +} \ No newline at end of file diff --git a/test/test_suite2/types/enum_param.c3 b/test/test_suite2/types/enum_param.c3 new file mode 100644 index 000000000..f369a64ed --- /dev/null +++ b/test/test_suite2/types/enum_param.c3 @@ -0,0 +1,12 @@ +enum Foo +{ + A, B +} + +fn void test(Foo f) +{} + +fn void test2() +{ + test(Foo.A); +} \ No newline at end of file diff --git a/test/test_suite2/types/enum_parse_errors.c3 b/test/test_suite2/types/enum_parse_errors.c3 new file mode 100644 index 000000000..a46e18efa --- /dev/null +++ b/test/test_suite2/types/enum_parse_errors.c3 @@ -0,0 +1,22 @@ + +enum EnumWithErrorWithMissingName : int (int) // #error: The parameter must be named +{ + TEST +} + +enum EnumWithErrorData : int (int // #error: end of the parameter list +{ + TEST +} + +enum EnumWithErrorData2 : int (int, int bar) // #error: The parameter must be named +{ + TEST +} + + +enum EnumTestErrorType3 : int +{ + A, + A // #error: This enum constant is declared twice +} \ No newline at end of file diff --git a/test/test_suite2/types/recursive_array.c3 b/test/test_suite2/types/recursive_array.c3 new file mode 100644 index 000000000..199a6c013 --- /dev/null +++ b/test/test_suite2/types/recursive_array.c3 @@ -0,0 +1,4 @@ +struct Qq +{ + Qq[3]* a; +} \ No newline at end of file diff --git a/test/test_suite2/types/recursive_typedef.c3 b/test/test_suite2/types/recursive_typedef.c3 new file mode 100644 index 000000000..7d264a9d7 --- /dev/null +++ b/test/test_suite2/types/recursive_typedef.c3 @@ -0,0 +1,9 @@ +define Number2 = Number1; // #error: Recursive definition of 'Number2' +define Number1 = Number2; + +define Number = Number; // #error: Recursive definition of 'Number' + + +define Loop2 = Loop; // #error: Recursive definition of 'Loop2' +define Loop3 = Loop2; +define Loop = Loop3; diff --git a/test/test_suite2/types/redefinition.c3 b/test/test_suite2/types/redefinition.c3 new file mode 100644 index 000000000..a2e16bd89 --- /dev/null +++ b/test/test_suite2/types/redefinition.c3 @@ -0,0 +1,2 @@ +define Number = int; +define Number = uint; // #error: 'Number' would shadow a previous declaration. \ No newline at end of file diff --git a/test/test_suite2/types/typedefs.c3 b/test/test_suite2/types/typedefs.c3 new file mode 100644 index 000000000..354e99554 --- /dev/null +++ b/test/test_suite2/types/typedefs.c3 @@ -0,0 +1,11 @@ +define Arr = int[4]; + +Arr a = { 3, 4, 5, 6 }; + +fn void test1() +{ + Arr b = { 3, 4, 5, 6 }; + int c = b; // #error: 'Arr' (int[4]) into 'int' + int d = a; // #error: 'Arr' (int[4]) into 'int' +} + diff --git a/test/test_suite2/types/various.c3 b/test/test_suite2/types/various.c3 new file mode 100644 index 000000000..3a93475fc --- /dev/null +++ b/test/test_suite2/types/various.c3 @@ -0,0 +1,5 @@ +func1 a = 1; // #error: A type name was expected + +fn void func1() {} + +uint b = -1; \ No newline at end of file diff --git a/test/test_suite2/unicode/commenting-out.c3 b/test/test_suite2/unicode/commenting-out.c3 new file mode 100644 index 000000000..2c9a908db --- /dev/null +++ b/test/test_suite2/unicode/commenting-out.c3 @@ -0,0 +1,10 @@ +// #error: Invalid encoding - Unbalanced bidirectional markers. +int main() { + bool isAdmin = false; + /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */ + printf("You are an admin.\n"); + /* end admins only ‮ { ⁦*/ + return 0; +} + + diff --git a/test/test_suite2/union/flexible_array_union.c3 b/test/test_suite2/union/flexible_array_union.c3 new file mode 100644 index 000000000..42bbe8276 --- /dev/null +++ b/test/test_suite2/union/flexible_array_union.c3 @@ -0,0 +1,5 @@ +union Zee +{ + int z; + int[*] y; // #error: Flexible array members not allowed in unions. +} \ No newline at end of file diff --git a/test/test_suite2/union/test_unions.c3 b/test/test_suite2/union/test_unions.c3 new file mode 100644 index 000000000..8f465442b --- /dev/null +++ b/test/test_suite2/union/test_unions.c3 @@ -0,0 +1,28 @@ +module test; + +union Qu +{ + Qu *x; +} + +union Xe +{ + char c; + int a, z; + long b; + void *b1; + struct qu + { + int a; + long z; + } +} + +fn Xe foo(Xe a) +{ + a.c = 123; + a.a = 39249; + a.b = 12301230123123i64; + a.z = 1; + return a; +} \ No newline at end of file diff --git a/test/test_suite2/union/union_codegen_const.c3t b/test/test_suite2/union/union_codegen_const.c3t new file mode 100644 index 000000000..a211ff248 --- /dev/null +++ b/test/test_suite2/union/union_codegen_const.c3t @@ -0,0 +1,20 @@ +module test; + +union Foo +{ + int a; + double b; +} + +private Foo f = { .a = 23 }; +private Foo g = { .b = 2.3 }; +private Foo h = { .a = 23, .b = 2.3 }; +Foo i = { .b = 2.3, .a = 23 }; + +// #expect: test.ll + +@test.f = protected unnamed_addr global { i32, [4 x i8] } { i32 23, [4 x i8] undef }, align 8 +@test.g = protected unnamed_addr global %Foo { double 2.300000e+00 }, align 8 +@test.h = protected unnamed_addr global %Foo { double 2.300000e+00 }, align 8 +@test.i = local_unnamed_addr global { i32, [4 x i8] } { i32 23, [4 x i8] undef }, align 8 + diff --git a/test/test_suite2/union/union_codegen_empty.c3t b/test/test_suite2/union/union_codegen_empty.c3t new file mode 100644 index 000000000..bd460b762 --- /dev/null +++ b/test/test_suite2/union/union_codegen_empty.c3t @@ -0,0 +1,44 @@ +union UnionA +{ + int a; +} + +union UnionB +{ + struct b + { + int a; + } + int c; + double d; +} + +fn void test() +{ + UnionA a = {}; + UnionA a2; + UnionB b = {}; + UnionB b2; + UnionB b3 = { .b = {} }; + UnionB b4 = { .b.a = 23, .c = 4, .d = 0.4, .b = {} }; +} + +/* #expect: union_codegen_empty.ll + +source_filena +define void @union_codegen_empty.test() #0 { +entry: + %a = alloca %UnionA, align 4 + %a2 = alloca %UnionA, align 4 + %b = alloca %UnionB, align 8 + %b2 = alloca %UnionB, align 8 + %b3 = alloca %UnionB, align 8 + %b4 = alloca %UnionB, align 8 + store i32 0, ptr %a, align 4 + store i32 0, ptr %a2, align 4 + call void @llvm.memset.p0.i64(ptr align 8 %b, i8 0, i64 8, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %b2, i8 0, i64 8, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %b3, i8 0, i64 8, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %b4, i8 0, i64 8, i1 false) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/union/union_codegen_overwrite_call.c3t b/test/test_suite2/union/union_codegen_overwrite_call.c3t new file mode 100644 index 000000000..305840dc5 --- /dev/null +++ b/test/test_suite2/union/union_codegen_overwrite_call.c3t @@ -0,0 +1,29 @@ +module test; + +union UnionB +{ + struct b + { + int a; + } + int c; + double d; +} + +extern fn int bar(); + +fn void test() +{ + UnionB b = { .c = bar(), .b = {} }; +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + %b = alloca %UnionB, align 8 + %0 = call i32 @bar() + store i32 %0, ptr %b, align 8 + store i32 0, ptr %b, align 8 + ret void +} diff --git a/test/test_suite2/union/union_in_struct.c3t b/test/test_suite2/union/union_in_struct.c3t new file mode 100644 index 000000000..64b09b4d8 --- /dev/null +++ b/test/test_suite2/union/union_in_struct.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 +module test; + +struct Foo +{ + char c; + union { + int a; + double b; + } + int z; +} + +Foo foo1 = { .a = 3, .z = 4 }; +Foo foo2 = { .b = 3, .z = 4 }; + +struct Blend_Map_Entry +{ + union vals { + float[5] colour; + double[2] point_Slope; + } +} + +Blend_Map_Entry a = { .vals = { .colour = { 1, 2, 3, 4, 5 } } }; +Blend_Map_Entry b = { .vals = { .point_Slope = { 6, 7 } } }; +Blend_Map_Entry c = { .vals.colour[2] = 1 }; +Blend_Map_Entry d = { .vals.colour = { 1, 2, 3, 4, 5 } }; + +fn void test(Blend_Map_Entry* foo) +{ +} + +// #expect: test.ll + + +%Blend_Map_Entry = type { %vals } +%vals = type { [2 x double], [8 x i8] } + +@test.foo1 = local_unnamed_addr global { i8, [4 x i8], { i32, [4 x i8] }, i32 } { i8 0, [4 x i8] undef, { i32, [4 x i8] } { i32 3, [4 x i8] undef }, i32 4 }, align 8 +@test.foo2 = local_unnamed_addr global %Foo { i8 0, %anon { double 3.000000e+00 }, i32 4 }, align 8 +@test.a = local_unnamed_addr global { { [5 x float], [4 x i8] } } { { [5 x float], [4 x i8] } { [5 x float] [float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00, float 5.000000e+00], [4 x i8] undef } }, align 8 +@test.b = local_unnamed_addr global %Blend_Map_Entry { %vals { [2 x double] [double 6.000000e+00, double 7.000000e+00], [8 x i8] undef } }, align 8 +@test.c = local_unnamed_addr global { { { [2 x float], float, [2 x float] }, [4 x i8] } } { { { [2 x float], float, [2 x float] }, [4 x i8] } { { [2 x float], float, [2 x float] } { [2 x float] zeroinitializer, float 1.000000e+00, [2 x float] zeroinitializer }, [4 x i8] undef } }, align 8 +@test.d = local_unnamed_addr global { { [5 x float], [4 x i8] } } { { [5 x float], [4 x i8] } { [5 x float] [float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00, float 5.000000e+00], [4 x i8] undef } }, align 8 diff --git a/test/test_suite2/union/union_member_voidcast.c3 b/test/test_suite2/union/union_member_voidcast.c3 new file mode 100644 index 000000000..aeea25047 --- /dev/null +++ b/test/test_suite2/union/union_member_voidcast.c3 @@ -0,0 +1,13 @@ +module test; + +union Xu +{ + void *b; +} + +fn Xu foo() +{ + Xu a; + a.b = (void*)(123); + return a; +} \ No newline at end of file diff --git a/test/test_suite2/variables/consts.c3 b/test/test_suite2/variables/consts.c3 new file mode 100644 index 000000000..e3138622f --- /dev/null +++ b/test/test_suite2/variables/consts.c3 @@ -0,0 +1,7 @@ +const int foo = 3; // #error: must be all upper case + +fn void foo(int i) +{ + const int x = i; // #error: must be all upper case + const int Y = i; +} \ No newline at end of file diff --git a/test/test_suite2/variant/variant_assign.c3t b/test/test_suite2/variant/variant_assign.c3t new file mode 100644 index 000000000..1136ba73c --- /dev/null +++ b/test/test_suite2/variant/variant_assign.c3t @@ -0,0 +1,335 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char*, ...); + +fn void test(variant z) +{ + switch (z) + { + case int: + printf("int: %d\n", *z); + case double: + printf("double %f\n", *z); + default: + printf("Unknown type.\n"); + } +} +fn void test2(variant y) +{ + switch (z = y) + { + case int: + y = &&12; + printf("int: %d\n", *z); + case double: + printf("double %f\n", *z); + default: + printf("Unknown type.\n"); + } +} + +fn void test3(variant y) +{ + switch (z = *y) + { + case int: + printf("int: %d\n", z); + case double: + printf("double %f\n", z); + default: + printf("Unknown type.\n"); + } +} + +fn int main() +{ + test(&&123.0); + test(&&1); + test(&&true); + test2(&&123.5); + test2(&&1); + test2(&&true); + test3(&&124.0); + test3(&&2); + test3(&&true); + return 0; +} + +/* #expect: foo.ll + +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 +@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2 +@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1 + +define void @foo.test(i64 %0, ptr %1) #0 { +entry: + %z = alloca %variant, align 8 + %switch = alloca i64, align 8 + %z1 = alloca ptr, align 8 + %z4 = alloca ptr, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %z, i32 0, i32 0 + store i64 %0, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %z, i32 0, i32 1 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds %variant, ptr %z, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %6 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @.typeid.int to i64), %6 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + %7 = getelementptr inbounds %variant, ptr %z, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + store ptr %8, ptr %z1, align 8 + %9 = load ptr, ptr %z1, align 8 + %10 = load i32, ptr %9, align 8 + call void (ptr, ...) @printf(ptr @.str, i32 %10) + br label %switch.exit + +next_if: ; preds = %switch.entry + %eq2 = icmp eq i64 ptrtoint (ptr @.typeid.double to i64), %6 + br i1 %eq2, label %switch.case3, label %next_if5 + +switch.case3: ; preds = %next_if + %11 = getelementptr inbounds %variant, ptr %z, i32 0, i32 0 + %12 = load ptr, ptr %11, align 8 + store ptr %12, ptr %z4, align 8 + %13 = load ptr, ptr %z4, align 8 + %14 = load double, ptr %13, align 8 + call void (ptr, ...) @printf(ptr @.str.1, double %14) + br label %switch.exit + +next_if5: ; preds = %next_if + br label %switch.default + +switch.default: ; preds = %next_if5 + call void (ptr, ...) @printf(ptr @.str.2) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case3, %switch.case + ret void +} + +define void @foo.test2(i64 %0, ptr %1) #0 { +entry: + %y = alloca %variant, align 8 + %anon = alloca %variant, align 8 + %switch = alloca i64, align 8 + %z = alloca ptr, align 8 + %taddr = alloca i32, align 4 + %z3 = alloca ptr, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %y, i32 0, i32 0 + store i64 %0, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %y, i32 0, i32 1 + store ptr %1, ptr %3, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %anon, ptr align 8 %y, i32 16, i1 false) + %4 = getelementptr inbounds %variant, ptr %y, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %6 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @.typeid.int to i64), %6 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + %7 = getelementptr inbounds %variant, ptr %anon, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + store ptr %8, ptr %z, align 8 + store i32 12, ptr %taddr, align 4 + %9 = insertvalue %variant undef, ptr %taddr, 0 + %10 = insertvalue %variant %9, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %10, ptr %y, align 8 + %11 = load ptr, ptr %z, align 8 + %12 = load i32, ptr %11, align 8 + call void (ptr, ...) @printf(ptr @.str.3, i32 %12) + br label %switch.exit + +next_if: ; preds = %switch.entry + %eq1 = icmp eq i64 ptrtoint (ptr @.typeid.double to i64), %6 + br i1 %eq1, label %switch.case2, label %next_if4 + +switch.case2: ; preds = %next_if + %13 = getelementptr inbounds %variant, ptr %anon, i32 0, i32 0 + %14 = load ptr, ptr %13, align 8 + store ptr %14, ptr %z3, align 8 + %15 = load ptr, ptr %z3, align 8 + %16 = load double, ptr %15, align 8 + call void (ptr, ...) @printf(ptr @.str.4, double %16) + br label %switch.exit + +next_if4: ; preds = %next_if + br label %switch.default + +switch.default: ; preds = %next_if4 + call void (ptr, ...) @printf(ptr @.str.5) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case2, %switch.case + ret void +} + +define void @foo.test3(i64 %0, ptr %1) #0 { +entry: + %y = alloca %variant, align 8 + %anon = alloca %variant, align 8 + %switch = alloca i64, align 8 + %z = alloca i32, align 4 + %z3 = alloca double, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %y, i32 0, i32 0 + store i64 %0, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %y, i32 0, i32 1 + store ptr %1, ptr %3, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %anon, ptr align 8 %y, i32 16, i1 false) + %4 = getelementptr inbounds %variant, ptr %y, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %6 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @.typeid.int to i64), %6 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + %7 = getelementptr inbounds %variant, ptr %anon, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + %9 = load i32, ptr %8, align 8 + store i32 %9, ptr %z, align 4 + %10 = load i32, ptr %z, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %10) + br label %switch.exit + +next_if: ; preds = %switch.entry + %eq1 = icmp eq i64 ptrtoint (ptr @.typeid.double to i64), %6 + br i1 %eq1, label %switch.case2, label %next_if4 + +switch.case2: ; preds = %next_if + %11 = getelementptr inbounds %variant, ptr %anon, i32 0, i32 0 + %12 = load ptr, ptr %11, align 8 + %13 = load double, ptr %12, align 8 + store double %13, ptr %z3, align 8 + %14 = load double, ptr %z3, align 8 + call void (ptr, ...) @printf(ptr @.str.7, double %14) + br label %switch.exit + +next_if4: ; preds = %next_if + br label %switch.default + +switch.default: ; preds = %next_if4 + call void (ptr, ...) @printf(ptr @.str.8) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case2, %switch.case + ret void +} + +define i32 @main() #0 { +entry: + %taddr = alloca double, align 8 + %taddr1 = alloca %variant, align 8 + %taddr2 = alloca i32, align 4 + %taddr3 = alloca %variant, align 8 + %taddr6 = alloca i8, align 1 + %taddr7 = alloca %variant, align 8 + %taddr10 = alloca double, align 8 + %taddr11 = alloca %variant, align 8 + %taddr14 = alloca i32, align 4 + %taddr15 = alloca %variant, align 8 + %taddr18 = alloca i8, align 1 + %taddr19 = alloca %variant, align 8 + %taddr22 = alloca double, align 8 + %taddr23 = alloca %variant, align 8 + %taddr26 = alloca i32, align 4 + %taddr27 = alloca %variant, align 8 + %taddr30 = alloca i8, align 1 + %taddr31 = alloca %variant, align 8 + store double 1.230000e+02, ptr %taddr, align 8 + %0 = insertvalue %variant undef, ptr %taddr, 0 + %1 = insertvalue %variant %0, i64 ptrtoint (ptr @.typeid.double to i64), 1 + store %variant %1, ptr %taddr1, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %taddr1, i32 0, i32 0 + %lo = load i64, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %taddr1, i32 0, i32 1 + %hi = load ptr, ptr %3, align 8 + call void @foo.test(i64 %lo, ptr %hi) + store i32 1, ptr %taddr2, align 4 + %4 = insertvalue %variant undef, ptr %taddr2, 0 + %5 = insertvalue %variant %4, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %5, ptr %taddr3, align 8 + %6 = getelementptr inbounds { i64, ptr }, ptr %taddr3, i32 0, i32 0 + %lo4 = load i64, ptr %6, align 8 + %7 = getelementptr inbounds { i64, ptr }, ptr %taddr3, i32 0, i32 1 + %hi5 = load ptr, ptr %7, align 8 + call void @foo.test(i64 %lo4, ptr %hi5) + store i8 1, ptr %taddr6, align 1 + %8 = insertvalue %variant undef, ptr %taddr6, 0 + %9 = insertvalue %variant %8, i64 ptrtoint (ptr @.typeid.bool to i64), 1 + store %variant %9, ptr %taddr7, align 8 + %10 = getelementptr inbounds { i64, ptr }, ptr %taddr7, i32 0, i32 0 + %lo8 = load i64, ptr %10, align 8 + %11 = getelementptr inbounds { i64, ptr }, ptr %taddr7, i32 0, i32 1 + %hi9 = load ptr, ptr %11, align 8 + call void @foo.test(i64 %lo8, ptr %hi9) + store double 1.235000e+02, ptr %taddr10, align 8 + %12 = insertvalue %variant undef, ptr %taddr10, 0 + %13 = insertvalue %variant %12, i64 ptrtoint (ptr @.typeid.double to i64), 1 + store %variant %13, ptr %taddr11, align 8 + %14 = getelementptr inbounds { i64, ptr }, ptr %taddr11, i32 0, i32 0 + %lo12 = load i64, ptr %14, align 8 + %15 = getelementptr inbounds { i64, ptr }, ptr %taddr11, i32 0, i32 1 + %hi13 = load ptr, ptr %15, align 8 + call void @foo.test2(i64 %lo12, ptr %hi13) + store i32 1, ptr %taddr14, align 4 + %16 = insertvalue %variant undef, ptr %taddr14, 0 + %17 = insertvalue %variant %16, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %17, ptr %taddr15, align 8 + %18 = getelementptr inbounds { i64, ptr }, ptr %taddr15, i32 0, i32 0 + %lo16 = load i64, ptr %18, align 8 + %19 = getelementptr inbounds { i64, ptr }, ptr %taddr15, i32 0, i32 1 + %hi17 = load ptr, ptr %19, align 8 + call void @foo.test2(i64 %lo16, ptr %hi17) + store i8 1, ptr %taddr18, align 1 + %20 = insertvalue %variant undef, ptr %taddr18, 0 + %21 = insertvalue %variant %20, i64 ptrtoint (ptr @.typeid.bool to i64), 1 + store %variant %21, ptr %taddr19, align 8 + %22 = getelementptr inbounds { i64, ptr }, ptr %taddr19, i32 0, i32 0 + %lo20 = load i64, ptr %22, align 8 + %23 = getelementptr inbounds { i64, ptr }, ptr %taddr19, i32 0, i32 1 + %hi21 = load ptr, ptr %23, align 8 + call void @foo.test2(i64 %lo20, ptr %hi21) + store double 1.240000e+02, ptr %taddr22, align 8 + %24 = insertvalue %variant undef, ptr %taddr22, 0 + %25 = insertvalue %variant %24, i64 ptrtoint (ptr @.typeid.double to i64), 1 + store %variant %25, ptr %taddr23, align 8 + %26 = getelementptr inbounds { i64, ptr }, ptr %taddr23, i32 0, i32 0 + %lo24 = load i64, ptr %26, align 8 + %27 = getelementptr inbounds { i64, ptr }, ptr %taddr23, i32 0, i32 1 + %hi25 = load ptr, ptr %27, align 8 + call void @foo.test3(i64 %lo24, ptr %hi25) + store i32 2, ptr %taddr26, align 4 + %28 = insertvalue %variant undef, ptr %taddr26, 0 + %29 = insertvalue %variant %28, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %29, ptr %taddr27, align 8 + %30 = getelementptr inbounds { i64, ptr }, ptr %taddr27, i32 0, i32 0 + %lo28 = load i64, ptr %30, align 8 + %31 = getelementptr inbounds { i64, ptr }, ptr %taddr27, i32 0, i32 1 + %hi29 = load ptr, ptr %31, align 8 + call void @foo.test3(i64 %lo28, ptr %hi29) + store i8 1, ptr %taddr30, align 1 + %32 = insertvalue %variant undef, ptr %taddr30, 0 + %33 = insertvalue %variant %32, i64 ptrtoint (ptr @.typeid.bool to i64), 1 + store %variant %33, ptr %taddr31, align 8 + %34 = getelementptr inbounds { i64, ptr }, ptr %taddr31, i32 0, i32 0 + %lo32 = load i64, ptr %34, align 8 + %35 = getelementptr inbounds { i64, ptr }, ptr %taddr31, i32 0, i32 1 + %hi33 = load ptr, ptr %35, align 8 + call void @foo.test3(i64 %lo32, ptr %hi33) + ret i32 0 +} diff --git a/test/test_suite2/variant/variant_switch.c3t b/test/test_suite2/variant/variant_switch.c3t new file mode 100644 index 000000000..d680bd3d6 --- /dev/null +++ b/test/test_suite2/variant/variant_switch.c3t @@ -0,0 +1,142 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char*, ...); + +fn void test(variant z) +{ + switch (z) + { + case int: + printf("int: %d\n", *z); + *z = 3; + case double: + printf("double %f\n", *z); + default: + printf("Unknown type.\n"); + } + if (z.type == int.typeid) + { + printf("int: %d\n", *(int*)(z)); + } +} +fn int main() +{ + test(&&123.0); + test(&&1); + test(&&true); + return 0; +} + +/* #expect: foo.ll + +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 +@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2 +@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1 + +define void @foo.test(i64 %0, ptr %1) #0 { +entry: + %z = alloca %variant, align 8 + %switch = alloca i64, align 8 + %z1 = alloca ptr, align 8 + %z4 = alloca ptr, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %z, i32 0, i32 0 + store i64 %0, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %z, i32 0, i32 1 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds %variant, ptr %z, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %6 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @.typeid.int to i64), %6 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + %7 = getelementptr inbounds %variant, ptr %z, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + store ptr %8, ptr %z1, align 8 + %9 = load ptr, ptr %z1, align 8 + %10 = load i32, ptr %9, align 8 + call void (ptr, ...) @printf(ptr @.str, i32 %10) + %11 = load ptr, ptr %z1, align 8 + store i32 3, ptr %11, align 8 + br label %switch.exit + +next_if: ; preds = %switch.entry + %eq2 = icmp eq i64 ptrtoint (ptr @.typeid.double to i64), %6 + br i1 %eq2, label %switch.case3, label %next_if5 + +switch.case3: ; preds = %next_if + %12 = getelementptr inbounds %variant, ptr %z, i32 0, i32 0 + %13 = load ptr, ptr %12, align 8 + store ptr %13, ptr %z4, align 8 + %14 = load ptr, ptr %z4, align 8 + %15 = load double, ptr %14, align 8 + call void (ptr, ...) @printf(ptr @.str.1, double %15) + br label %switch.exit + +next_if5: ; preds = %next_if + br label %switch.default + +switch.default: ; preds = %next_if5 + call void (ptr, ...) @printf(ptr @.str.2) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case3, %switch.case + %16 = getelementptr inbounds %variant, ptr %z, i32 0, i32 1 + %17 = load i64, ptr %16, align 8 + %eq6 = icmp eq i64 %17, ptrtoint (ptr @.typeid.int to i64) + br i1 %eq6, label %if.then, label %if.exit + +if.then: ; preds = %switch.exit + %18 = getelementptr inbounds %variant, ptr %z, i32 0, i32 0 + %19 = load ptr, ptr %18, align 8 + %20 = load i32, ptr %19, align 8 + call void (ptr, ...) @printf(ptr @.str.3, i32 %20) + br label %if.exit + +if.exit: ; preds = %if.then, %switch.exit + ret void +} + +; Function Attrs: nounwind +define i32 @main() #0 { +entry: + %taddr = alloca double, align 8 + %taddr1 = alloca %variant, align 8 + %taddr2 = alloca i32, align 4 + %taddr3 = alloca %variant, align 8 + %taddr6 = alloca i8, align 1 + %taddr7 = alloca %variant, align 8 + store double 1.230000e+02, ptr %taddr, align 8 + %0 = insertvalue %variant undef, ptr %taddr, 0 + %1 = insertvalue %variant %0, i64 ptrtoint (ptr @.typeid.double to i64), 1 + store %variant %1, ptr %taddr1, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %taddr1, i32 0, i32 0 + %lo = load i64, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %taddr1, i32 0, i32 1 + %hi = load ptr, ptr %3, align 8 + call void @foo.test(i64 %lo, ptr %hi) + store i32 1, ptr %taddr2, align 4 + %4 = insertvalue %variant undef, ptr %taddr2, 0 + %5 = insertvalue %variant %4, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %5, ptr %taddr3, align 8 + %6 = getelementptr inbounds { i64, ptr }, ptr %taddr3, i32 0, i32 0 + %lo4 = load i64, ptr %6, align 8 + %7 = getelementptr inbounds { i64, ptr }, ptr %taddr3, i32 0, i32 1 + %hi5 = load ptr, ptr %7, align 8 + call void @foo.test(i64 %lo4, ptr %hi5) + store i8 1, ptr %taddr6, align 1 + %8 = insertvalue %variant undef, ptr %taddr6, 0 + %9 = insertvalue %variant %8, i64 ptrtoint (ptr @.typeid.bool to i64), 1 + store %variant %9, ptr %taddr7, align 8 + %10 = getelementptr inbounds { i64, ptr }, ptr %taddr7, i32 0, i32 0 + %lo8 = load i64, ptr %10, align 8 + %11 = getelementptr inbounds { i64, ptr }, ptr %taddr7, i32 0, i32 1 + %hi9 = load ptr, ptr %11, align 8 + call void @foo.test(i64 %lo8, ptr %hi9) + ret i32 0 +} diff --git a/test/test_suite2/variant/variant_test.c3t b/test/test_suite2/variant/variant_test.c3t new file mode 100644 index 000000000..85d701c3d --- /dev/null +++ b/test/test_suite2/variant/variant_test.c3t @@ -0,0 +1,318 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*, ...); + +fn void test(variant x) +{ + switch (x.type) + { + case int: + printf("Was int\n"); + case double: + printf("Was double\n"); + case variant: + printf("Was variant\n"); + case int*: + printf("Was int*\n"); + default: + printf("Unknown type\n"); + } +} + +fn void test_all(variant... y) +{ + foreach (element : y) + { + test(element); + } +} + +fn void main() +{ + variant x = &&1; + int z; + variant y = &z; + typeid g = y.type; + typeid h = x.type; + if (y.type == int.typeid) + { + printf("y int match\n"); + } + if (x.type == int.typeid) + { + printf("x int match\n"); + } + y = &&1.0; + x = &x; + if (y.type == int.typeid) + { + printf("y int match\n"); + } + if (x.type == int.typeid) + { + printf("x int match\n"); + } + test(x); + test(&&1.0); + test(&&1); + test(&&true); + printf("----\n"); + int* df = null; + test_all(x, x, &&1.0, &x, &df); +} + +/* #expect: foo.ll + + +%variant = type { ptr, i64 } +%"variant[]" = type { ptr, i64 } + +@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2 +@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2 +@.typeid.variant = linkonce constant { i8 } { i8 7 }, align 1 +@".typeid.int*" = linkonce constant { i8, i64 } { i8 15, i64 ptrtoint (ptr @.typeid.int to i64) }, align 8 +@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1 + +define void @foo.test(i64 %0, ptr %1) #0 { +entry: + %x = alloca %variant, align 8 + %switch = alloca i64, align 8 + %2 = getelementptr inbounds { i64, ptr }, ptr %x, i32 0, i32 0 + store i64 %0, ptr %2, align 8 + %3 = getelementptr inbounds { i64, ptr }, ptr %x, i32 0, i32 1 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds %variant, ptr %x, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %6 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @.typeid.int to i64), %6 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + call void (ptr, ...) @printf(ptr @.str) + br label %switch.exit + +next_if: ; preds = %switch.entry + %eq1 = icmp eq i64 ptrtoint (ptr @.typeid.double to i64), %6 + br i1 %eq1, label %switch.case2, label %next_if3 + +switch.case2: ; preds = %next_if + call void (ptr, ...) @printf(ptr @.str.1) + br label %switch.exit + +next_if3: ; preds = %next_if + %eq4 = icmp eq i64 ptrtoint (ptr @.typeid.variant to i64), %6 + br i1 %eq4, label %switch.case5, label %next_if6 + +switch.case5: ; preds = %next_if3 + call void (ptr, ...) @printf(ptr @.str.2) + br label %switch.exit + +next_if6: ; preds = %next_if3 + %eq7 = icmp eq i64 ptrtoint (ptr @".typeid.int*" to i64), %6 + br i1 %eq7, label %switch.case8, label %next_if9 + +switch.case8: ; preds = %next_if6 + call void (ptr, ...) @printf(ptr @.str.3) + br label %switch.exit + +next_if9: ; preds = %next_if6 + br label %switch.default + +switch.default: ; preds = %next_if9 + call void (ptr, ...) @printf(ptr @.str.4) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case8, %switch.case5, %switch.case2, %switch.case + ret void +} + +; Function Attrs: nounwind +define void @foo.test_all(ptr %0, i64 %1) #0 { +entry: + %y = alloca %"variant[]", align 8 + %anon = alloca i64, align 8 + %anon1 = alloca i64, align 8 + %element = alloca %variant, align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %y, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %y, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + store i64 0, ptr %anon, align 8 + %4 = getelementptr inbounds %"variant[]", ptr %y, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %anon1, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %6 = load i64, ptr %anon, align 8 + %7 = load i64, ptr %anon1, align 8 + %lt = icmp ult i64 %6, %7 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %8 = getelementptr inbounds %"variant[]", ptr %y, i32 0, i32 0 + %9 = load ptr, ptr %8, align 8 + %10 = load i64, ptr %anon, align 8 + %ptroffset = getelementptr inbounds %variant, ptr %9, i64 %10 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %element, ptr align 8 %ptroffset, i32 16, i1 false) + %11 = getelementptr inbounds { i64, ptr }, ptr %element, i32 0, i32 0 + %lo = load i64, ptr %11, align 8 + %12 = getelementptr inbounds { i64, ptr }, ptr %element, i32 0, i32 1 + %hi = load ptr, ptr %12, align 8 + call void @foo.test(i64 %lo, ptr %hi) + %13 = load i64, ptr %anon, align 8 + %add = add i64 %13, 1 + store i64 %add, ptr %anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} + +; Function Attrs: nounwind +define void @foo.main() #0 { +entry: + %x = alloca %variant, align 8 + %taddr = alloca i32, align 4 + %z = alloca i32, align 4 + %y = alloca %variant, align 8 + %g = alloca i64, align 8 + %h = alloca i64, align 8 + %taddr4 = alloca double, align 8 + %taddr11 = alloca double, align 8 + %taddr12 = alloca %variant, align 8 + %taddr15 = alloca i32, align 4 + %taddr16 = alloca %variant, align 8 + %taddr19 = alloca i8, align 1 + %taddr20 = alloca %variant, align 8 + %df = alloca ptr, align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [5 x %variant], align 16 + %taddr23 = alloca double, align 8 + store i32 1, ptr %taddr, align 4 + %0 = insertvalue %variant undef, ptr %taddr, 0 + %1 = insertvalue %variant %0, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %1, ptr %x, align 8 + store i32 0, ptr %z, align 4 + %2 = insertvalue %variant undef, ptr %z, 0 + %3 = insertvalue %variant %2, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %3, ptr %y, align 8 + %4 = getelementptr inbounds %variant, ptr %y, i32 0, i32 1 + %5 = load i64, ptr %4, align 8 + store i64 %5, ptr %g, align 8 + %6 = getelementptr inbounds %variant, ptr %x, i32 0, i32 1 + %7 = load i64, ptr %6, align 8 + store i64 %7, ptr %h, align 8 + %8 = getelementptr inbounds %variant, ptr %y, i32 0, i32 1 + %9 = load i64, ptr %8, align 8 + %eq = icmp eq i64 %9, ptrtoint (ptr @.typeid.int to i64) + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + call void (ptr, ...) @printf(ptr @.str.5) + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %10 = getelementptr inbounds %variant, ptr %x, i32 0, i32 1 + %11 = load i64, ptr %10, align 8 + %eq1 = icmp eq i64 %11, ptrtoint (ptr @.typeid.int to i64) + br i1 %eq1, label %if.then2, label %if.exit3 + +if.then2: ; preds = %if.exit + call void (ptr, ...) @printf(ptr @.str.6) + br label %if.exit3 + +if.exit3: ; preds = %if.then2, %if.exit + store double 1.000000e+00, ptr %taddr4, align 8 + %12 = insertvalue %variant undef, ptr %taddr4, 0 + %13 = insertvalue %variant %12, i64 ptrtoint (ptr @.typeid.double to i64), 1 + store %variant %13, ptr %y, align 8 + %14 = insertvalue %variant undef, ptr %x, 0 + %15 = insertvalue %variant %14, i64 ptrtoint (ptr @.typeid.variant to i64), 1 + store %variant %15, ptr %x, align 8 + %16 = getelementptr inbounds %variant, ptr %y, i32 0, i32 1 + %17 = load i64, ptr %16, align 8 + %eq5 = icmp eq i64 %17, ptrtoint (ptr @.typeid.int to i64) + br i1 %eq5, label %if.then6, label %if.exit7 + +if.then6: ; preds = %if.exit3 + call void (ptr, ...) @printf(ptr @.str.7) + br label %if.exit7 + +if.exit7: ; preds = %if.then6, %if.exit3 + %18 = getelementptr inbounds %variant, ptr %x, i32 0, i32 1 + %19 = load i64, ptr %18, align 8 + %eq8 = icmp eq i64 %19, ptrtoint (ptr @.typeid.int to i64) + br i1 %eq8, label %if.then9, label %if.exit10 + +if.then9: ; preds = %if.exit7 + call void (ptr, ...) @printf(ptr @.str.8) + br label %if.exit10 + +if.exit10: ; preds = %if.then9, %if.exit7 + %20 = getelementptr inbounds { i64, ptr }, ptr %x, i32 0, i32 0 + %lo = load i64, ptr %20, align 8 + %21 = getelementptr inbounds { i64, ptr }, ptr %x, i32 0, i32 1 + %hi = load ptr, ptr %21, align 8 + call void @foo.test(i64 %lo, ptr %hi) + store double 1.000000e+00, ptr %taddr11, align 8 + %22 = insertvalue %variant undef, ptr %taddr11, 0 + %23 = insertvalue %variant %22, i64 ptrtoint (ptr @.typeid.double to i64), 1 + store %variant %23, ptr %taddr12, align 8 + %24 = getelementptr inbounds { i64, ptr }, ptr %taddr12, i32 0, i32 0 + %lo13 = load i64, ptr %24, align 8 + %25 = getelementptr inbounds { i64, ptr }, ptr %taddr12, i32 0, i32 1 + %hi14 = load ptr, ptr %25, align 8 + call void @foo.test(i64 %lo13, ptr %hi14) + store i32 1, ptr %taddr15, align 4 + %26 = insertvalue %variant undef, ptr %taddr15, 0 + %27 = insertvalue %variant %26, i64 ptrtoint (ptr @.typeid.int to i64), 1 + store %variant %27, ptr %taddr16, align 8 + %28 = getelementptr inbounds { i64, ptr }, ptr %taddr16, i32 0, i32 0 + %lo17 = load i64, ptr %28, align 8 + %29 = getelementptr inbounds { i64, ptr }, ptr %taddr16, i32 0, i32 1 + %hi18 = load ptr, ptr %29, align 8 + call void @foo.test(i64 %lo17, ptr %hi18) + store i8 1, ptr %taddr19, align 1 + %30 = insertvalue %variant undef, ptr %taddr19, 0 + %31 = insertvalue %variant %30, i64 ptrtoint (ptr @.typeid.bool to i64), 1 + store %variant %31, ptr %taddr20, align 8 + %32 = getelementptr inbounds { i64, ptr }, ptr %taddr20, i32 0, i32 0 + %lo21 = load i64, ptr %32, align 8 + %33 = getelementptr inbounds { i64, ptr }, ptr %taddr20, i32 0, i32 1 + %hi22 = load ptr, ptr %33, align 8 + call void @foo.test(i64 %lo21, ptr %hi22) + call void (ptr, ...) @printf(ptr @.str.9) + store ptr null, ptr %df, align 8 + %34 = getelementptr inbounds [5 x %variant], ptr %varargslots, i64 0, i64 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %34, ptr align 8 %x, i32 16, i1 false) + %35 = getelementptr inbounds [5 x %variant], ptr %varargslots, i64 0, i64 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %35, ptr align 8 %x, i32 16, i1 false) + store double 1.000000e+00, ptr %taddr23, align 8 + %36 = insertvalue %variant undef, ptr %taddr23, 0 + %37 = insertvalue %variant %36, i64 ptrtoint (ptr @.typeid.double to i64), 1 + %38 = getelementptr inbounds [5 x %variant], ptr %varargslots, i64 0, i64 2 + store %variant %37, ptr %38, align 16 + %39 = insertvalue %variant undef, ptr %x, 0 + %40 = insertvalue %variant %39, i64 ptrtoint (ptr @.typeid.variant to i64), 1 + %41 = getelementptr inbounds [5 x %variant], ptr %varargslots, i64 0, i64 3 + store %variant %40, ptr %41, align 16 + %42 = insertvalue %variant undef, ptr %df, 0 + %43 = insertvalue %variant %42, i64 ptrtoint (ptr @".typeid.int*" to i64), 1 + %44 = getelementptr inbounds [5 x %variant], ptr %varargslots, i64 0, i64 4 + store %variant %43, ptr %44, align 16 + %45 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 5, ptr %45, align 8 + %46 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %46, align 8 + %47 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo24 = load ptr, ptr %47, align 8 + %48 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi25 = load i64, ptr %48, align 8 + call void @foo.test_all(ptr %lo24, i64 %hi25) + ret void +} diff --git a/test/test_suite2/vector/vector_bit.c3t b/test/test_suite2/vector/vector_bit.c3t new file mode 100644 index 000000000..ef981dce7 --- /dev/null +++ b/test/test_suite2/vector/vector_bit.c3t @@ -0,0 +1,154 @@ +// #target: macos-x64 + +import libc; + +fn void testf() +{ + float[<4>] y = { 0, 2, 3, 0 }; + int[<4>] w = !y; + libc::printf("Notf %d %d %d %d\n", w[0], w[1], w[2], w[3]); +} + +fn void testi() +{ + int[<4>] y = { 1, 2, 3, 4 }; + int[<4>] z = { 2, 3, 13, -100 }; + int[<4>] w; + w = y & z; + libc::printf("And %d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y | z; + libc::printf("Or %d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y ^ z; + libc::printf("Xor %d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = ~y; + libc::printf("BitNeg %d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = -y; + libc::printf("Neg %d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = !y; + w = { -1, 13, 0, 0 }; + w = !w; + libc::printf("Not %d %d %d %d\n", w[0], w[1], w[2], w[3]); +} + +fn void main() +{ + testf(); + testi(); +} + +/* #expect: vector_bit.ll + +define void @vector_bit.testf() #0 { +entry: + %y = alloca <4 x float>, align 16 + %w = alloca <4 x i32>, align 16 + store <4 x float> , ptr %y, align 16 + %0 = load <4 x float>, ptr %y, align 16 + %not = fcmp une <4 x float> %0, zeroinitializer + %1 = sext <4 x i1> %not to <4 x i32> + store <4 x i32> %1, ptr %w, align 16 + %2 = load <4 x i32>, ptr %w, align 16 + %3 = extractelement <4 x i32> %2, i64 0 + %4 = load <4 x i32>, ptr %w, align 16 + %5 = extractelement <4 x i32> %4, i64 1 + %6 = load <4 x i32>, ptr %w, align 16 + %7 = extractelement <4 x i32> %6, i64 2 + %8 = load <4 x i32>, ptr %w, align 16 + %9 = extractelement <4 x i32> %8, i64 3 + %10 = call i32 (ptr, ...) @printf(ptr @.str, i32 %3, i32 %5, i32 %7, i32 %9) + ret void +} + +; Function Attrs: nounwind +define void @vector_bit.testi() #0 { +entry: + %y = alloca <4 x i32>, align 16 + %z = alloca <4 x i32>, align 16 + %w = alloca <4 x i32>, align 16 + store <4 x i32> , ptr %y, align 16 + store <4 x i32> , ptr %z, align 16 + store <4 x i32> zeroinitializer, ptr %w, align 16 + %0 = load <4 x i32>, ptr %y, align 16 + %1 = load <4 x i32>, ptr %z, align 16 + %and = and <4 x i32> %0, %1 + store <4 x i32> %and, ptr %w, align 16 + %2 = load <4 x i32>, ptr %w, align 16 + %3 = extractelement <4 x i32> %2, i64 0 + %4 = load <4 x i32>, ptr %w, align 16 + %5 = extractelement <4 x i32> %4, i64 1 + %6 = load <4 x i32>, ptr %w, align 16 + %7 = extractelement <4 x i32> %6, i64 2 + %8 = load <4 x i32>, ptr %w, align 16 + %9 = extractelement <4 x i32> %8, i64 3 + %10 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %3, i32 %5, i32 %7, i32 %9) + %11 = load <4 x i32>, ptr %y, align 16 + %12 = load <4 x i32>, ptr %z, align 16 + %or = or <4 x i32> %11, %12 + store <4 x i32> %or, ptr %w, align 16 + %13 = load <4 x i32>, ptr %w, align 16 + %14 = extractelement <4 x i32> %13, i64 0 + %15 = load <4 x i32>, ptr %w, align 16 + %16 = extractelement <4 x i32> %15, i64 1 + %17 = load <4 x i32>, ptr %w, align 16 + %18 = extractelement <4 x i32> %17, i64 2 + %19 = load <4 x i32>, ptr %w, align 16 + %20 = extractelement <4 x i32> %19, i64 3 + %21 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %14, i32 %16, i32 %18, i32 %20) + %22 = load <4 x i32>, ptr %y, align 16 + %23 = load <4 x i32>, ptr %z, align 16 + %xor = xor <4 x i32> %22, %23 + store <4 x i32> %xor, ptr %w, align 16 + %24 = load <4 x i32>, ptr %w, align 16 + %25 = extractelement <4 x i32> %24, i64 0 + %26 = load <4 x i32>, ptr %w, align 16 + %27 = extractelement <4 x i32> %26, i64 1 + %28 = load <4 x i32>, ptr %w, align 16 + %29 = extractelement <4 x i32> %28, i64 2 + %30 = load <4 x i32>, ptr %w, align 16 + %31 = extractelement <4 x i32> %30, i64 3 + %32 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 %25, i32 %27, i32 %29, i32 %31) + %33 = load <4 x i32>, ptr %y, align 16 + %bnot = xor <4 x i32> %33, + store <4 x i32> %bnot, ptr %w, align 16 + %34 = load <4 x i32>, ptr %w, align 16 + %35 = extractelement <4 x i32> %34, i64 0 + %36 = load <4 x i32>, ptr %w, align 16 + %37 = extractelement <4 x i32> %36, i64 1 + %38 = load <4 x i32>, ptr %w, align 16 + %39 = extractelement <4 x i32> %38, i64 2 + %40 = load <4 x i32>, ptr %w, align 16 + %41 = extractelement <4 x i32> %40, i64 3 + %42 = call i32 (ptr, ...) @printf(ptr @.str.4, i32 %35, i32 %37, i32 %39, i32 %41) + %43 = load <4 x i32>, ptr %y, align 16 + %44 = load <4 x i32>, ptr %y, align 16 + %neg = sub <4 x i32> zeroinitializer, %44 + store <4 x i32> %neg, ptr %w, align 16 + %45 = load <4 x i32>, ptr %w, align 16 + %46 = extractelement <4 x i32> %45, i64 0 + %47 = load <4 x i32>, ptr %w, align 16 + %48 = extractelement <4 x i32> %47, i64 1 + %49 = load <4 x i32>, ptr %w, align 16 + %50 = extractelement <4 x i32> %49, i64 2 + %51 = load <4 x i32>, ptr %w, align 16 + %52 = extractelement <4 x i32> %51, i64 3 + %53 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %46, i32 %48, i32 %50, i32 %52) + %54 = load <4 x i32>, ptr %y, align 16 + %not = icmp eq <4 x i32> %54, zeroinitializer + %55 = sext <4 x i1> %not to <4 x i32> + store <4 x i32> %55, ptr %w, align 16 + store <4 x i32> , ptr %w, align 16 + %56 = load <4 x i32>, ptr %w, align 16 + %not1 = icmp eq <4 x i32> %56, zeroinitializer + %57 = sext <4 x i1> %not1 to <4 x i32> + store <4 x i32> %57, ptr %w, align 16 + %58 = load <4 x i32>, ptr %w, align 16 + %59 = extractelement <4 x i32> %58, i64 0 + %60 = load <4 x i32>, ptr %w, align 16 + %61 = extractelement <4 x i32> %60, i64 1 + %62 = load <4 x i32>, ptr %w, align 16 + %63 = extractelement <4 x i32> %62, i64 2 + %64 = load <4 x i32>, ptr %w, align 16 + %65 = extractelement <4 x i32> %64, i64 3 + %66 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %59, i32 %61, i32 %63, i32 %65) + ret void +} diff --git a/test/test_suite2/vector/vector_incdec.c3t b/test/test_suite2/vector/vector_incdec.c3t new file mode 100644 index 000000000..c9bd25e1e --- /dev/null +++ b/test/test_suite2/vector/vector_incdec.c3t @@ -0,0 +1,190 @@ +// #target: macos-x64 +import libc; + +fn void testf() +{ + float[<4>] y = { 1, 2, 3, 4 }; + float[<4>] z = { 2, 2, 2, -100 }; + y += z; + libc::printf("Add %f %f %f %f\n", y[0], y[1], y[2], y[3]); + y++; + libc::printf("Inc %f %f %f %f\n", y[0], y[1], y[2], y[3]); + ++y; + libc::printf("Inc %f %f %f %f\n", y[0], y[1], y[2], y[3]); + y--; + libc::printf("Dec %f %f %f %f\n", y[0], y[1], y[2], y[3]); +} + +fn void testi() +{ + int[<4>] y = { 1, 2, 3, 4 }; + int[<4>] z = { 2, 2, 2, -100 }; + y += z; + libc::printf("Add %d %d %d %d\n", y[0], y[1], y[2], y[3]); + y++; + libc::printf("Inc %d %d %d %d\n", y[0], y[1], y[2], y[3]); + ++y; + libc::printf("Inc %d %d %d %d\n", y[0], y[1], y[2], y[3]); + int[<4>]w = y--; + libc::printf("Dec %d %d %d %d\n", y[0], y[1], y[2], y[3]); + libc::printf("Original %d %d %d %d\n", w[0], w[1], w[2], w[3]); +} + +fn void main() +{ + testf(); + testi(); +} + +/* #expect: vector_incdec.ll + +define void @vector_incdec.testf() #0 { +entry: + %y = alloca <4 x float>, align 16 + %z = alloca <4 x float>, align 16 + store <4 x float> , ptr %y, align 16 + store <4 x float> , ptr %z, align 16 + %0 = load <4 x float>, ptr %y, align 16 + %1 = load <4 x float>, ptr %z, align 16 + %fadd = fadd <4 x float> %0, %1 + store <4 x float> %fadd, ptr %y, align 16 + %2 = load <4 x float>, ptr %y, align 16 + %3 = extractelement <4 x float> %2, i64 0 + %fpfpext = fpext float %3 to double + %4 = load <4 x float>, ptr %y, align 16 + %5 = extractelement <4 x float> %4, i64 1 + %fpfpext1 = fpext float %5 to double + %6 = load <4 x float>, ptr %y, align 16 + %7 = extractelement <4 x float> %6, i64 2 + %fpfpext2 = fpext float %7 to double + %8 = load <4 x float>, ptr %y, align 16 + %9 = extractelement <4 x float> %8, i64 3 + %fpfpext3 = fpext float %9 to double + %10 = call i32 (ptr, ...) @printf(ptr @.str, double %fpfpext, double %fpfpext1, double %fpfpext2, double %fpfpext3) + %11 = load <4 x float>, ptr %y, align 16 + %fincdec = fadd <4 x float> %11, + store <4 x float> %fincdec, ptr %y, align 16 + %12 = load <4 x float>, ptr %y, align 16 + %13 = extractelement <4 x float> %12, i64 0 + %fpfpext4 = fpext float %13 to double + %14 = load <4 x float>, ptr %y, align 16 + %15 = extractelement <4 x float> %14, i64 1 + %fpfpext5 = fpext float %15 to double + %16 = load <4 x float>, ptr %y, align 16 + %17 = extractelement <4 x float> %16, i64 2 + %fpfpext6 = fpext float %17 to double + %18 = load <4 x float>, ptr %y, align 16 + %19 = extractelement <4 x float> %18, i64 3 + %fpfpext7 = fpext float %19 to double + %20 = call i32 (ptr, ...) @printf(ptr @.str.1, double %fpfpext4, double %fpfpext5, double %fpfpext6, double %fpfpext7) + %21 = load <4 x float>, ptr %y, align 16 + %fincdec8 = fadd <4 x float> %21, + store <4 x float> %fincdec8, ptr %y, align 16 + %22 = load <4 x float>, ptr %y, align 16 + %23 = extractelement <4 x float> %22, i64 0 + %fpfpext9 = fpext float %23 to double + %24 = load <4 x float>, ptr %y, align 16 + %25 = extractelement <4 x float> %24, i64 1 + %fpfpext10 = fpext float %25 to double + %26 = load <4 x float>, ptr %y, align 16 + %27 = extractelement <4 x float> %26, i64 2 + %fpfpext11 = fpext float %27 to double + %28 = load <4 x float>, ptr %y, align 16 + %29 = extractelement <4 x float> %28, i64 3 + %fpfpext12 = fpext float %29 to double + %30 = call i32 (ptr, ...) @printf(ptr @.str.2, double %fpfpext9, double %fpfpext10, double %fpfpext11, double %fpfpext12) + %31 = load <4 x float>, ptr %y, align 16 + %fincdec13 = fadd <4 x float> %31, + store <4 x float> %fincdec13, ptr %y, align 16 + %32 = load <4 x float>, ptr %y, align 16 + %33 = extractelement <4 x float> %32, i64 0 + %fpfpext14 = fpext float %33 to double + %34 = load <4 x float>, ptr %y, align 16 + %35 = extractelement <4 x float> %34, i64 1 + %fpfpext15 = fpext float %35 to double + %36 = load <4 x float>, ptr %y, align 16 + %37 = extractelement <4 x float> %36, i64 2 + %fpfpext16 = fpext float %37 to double + %38 = load <4 x float>, ptr %y, align 16 + %39 = extractelement <4 x float> %38, i64 3 + %fpfpext17 = fpext float %39 to double + %40 = call i32 (ptr, ...) @printf(ptr @.str.3, double %fpfpext14, double %fpfpext15, double %fpfpext16, double %fpfpext17) + ret void +} + +; Function Attrs: nounwind +define void @vector_incdec.testi() #0 { +entry: + %y = alloca <4 x i32>, align 16 + %z = alloca <4 x i32>, align 16 + %w = alloca <4 x i32>, align 16 + store <4 x i32> , ptr %y, align 16 + store <4 x i32> , ptr %z, align 16 + %0 = load <4 x i32>, ptr %y, align 16 + %1 = load <4 x i32>, ptr %z, align 16 + %add = add <4 x i32> %0, %1 + store <4 x i32> %add, ptr %y, align 16 + %2 = load <4 x i32>, ptr %y, align 16 + %3 = extractelement <4 x i32> %2, i64 0 + %4 = load <4 x i32>, ptr %y, align 16 + %5 = extractelement <4 x i32> %4, i64 1 + %6 = load <4 x i32>, ptr %y, align 16 + %7 = extractelement <4 x i32> %6, i64 2 + %8 = load <4 x i32>, ptr %y, align 16 + %9 = extractelement <4 x i32> %8, i64 3 + %10 = call i32 (ptr, ...) @printf(ptr @.str.4, i32 %3, i32 %5, i32 %7, i32 %9) + %11 = load <4 x i32>, ptr %y, align 16 + %add1 = add <4 x i32> %11, + store <4 x i32> %add1, ptr %y, align 16 + %12 = load <4 x i32>, ptr %y, align 16 + %13 = extractelement <4 x i32> %12, i64 0 + %14 = load <4 x i32>, ptr %y, align 16 + %15 = extractelement <4 x i32> %14, i64 1 + %16 = load <4 x i32>, ptr %y, align 16 + %17 = extractelement <4 x i32> %16, i64 2 + %18 = load <4 x i32>, ptr %y, align 16 + %19 = extractelement <4 x i32> %18, i64 3 + %20 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %13, i32 %15, i32 %17, i32 %19) + %21 = load <4 x i32>, ptr %y, align 16 + %add2 = add <4 x i32> %21, + store <4 x i32> %add2, ptr %y, align 16 + %22 = load <4 x i32>, ptr %y, align 16 + %23 = extractelement <4 x i32> %22, i64 0 + %24 = load <4 x i32>, ptr %y, align 16 + %25 = extractelement <4 x i32> %24, i64 1 + %26 = load <4 x i32>, ptr %y, align 16 + %27 = extractelement <4 x i32> %26, i64 2 + %28 = load <4 x i32>, ptr %y, align 16 + %29 = extractelement <4 x i32> %28, i64 3 + %30 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %23, i32 %25, i32 %27, i32 %29) + %31 = load <4 x i32>, ptr %y, align 16 + %sub = sub <4 x i32> %31, + store <4 x i32> %sub, ptr %y, align 16 + store <4 x i32> %31, ptr %w, align 16 + %32 = load <4 x i32>, ptr %y, align 16 + %33 = extractelement <4 x i32> %32, i64 0 + %34 = load <4 x i32>, ptr %y, align 16 + %35 = extractelement <4 x i32> %34, i64 1 + %36 = load <4 x i32>, ptr %y, align 16 + %37 = extractelement <4 x i32> %36, i64 2 + %38 = load <4 x i32>, ptr %y, align 16 + %39 = extractelement <4 x i32> %38, i64 3 + %40 = call i32 (ptr, ...) @printf(ptr @.str.7, i32 %33, i32 %35, i32 %37, i32 %39) + %41 = load <4 x i32>, ptr %w, align 16 + %42 = extractelement <4 x i32> %41, i64 0 + %43 = load <4 x i32>, ptr %w, align 16 + %44 = extractelement <4 x i32> %43, i64 1 + %45 = load <4 x i32>, ptr %w, align 16 + %46 = extractelement <4 x i32> %45, i64 2 + %47 = load <4 x i32>, ptr %w, align 16 + %48 = extractelement <4 x i32> %47, i64 3 + %49 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %42, i32 %44, i32 %46, i32 %48) + ret void +} + +define void @vector_incdec.main() #0 { +entry: + call void @vector_incdec.testf() + call void @vector_incdec.testi() + ret void +} diff --git a/test/test_suite2/vector/vector_init.c3t b/test/test_suite2/vector/vector_init.c3t new file mode 100644 index 000000000..402fbd9bc --- /dev/null +++ b/test/test_suite2/vector/vector_init.c3t @@ -0,0 +1,53 @@ +// #target: macos-x64 +int[<4>] baz = { 1, 4, 5, 7 }; + +fn void main() +{ + int[<4>] foo = { 1, 2, 3, 4 }; + int z = foo[0]; + foo[2] = z + 1; + int[<4>] bar = {}; + int[<4>] bar2 = { 1, z, 3, 4 }; + int[<4>] bar3 = { [1] = z }; + int[<4>] bar4 = { [0..3] = z }; +} + +/* #expect: vector_init.ll + +@vector_init.baz = local_unnamed_addr global <4 x i32> , align 16 + +; Function Attrs: nounwind +define void @vector_init.main() #0 { +entry: + %foo = alloca <4 x i32>, align 16 + %z = alloca i32, align 4 + %bar = alloca <4 x i32>, align 16 + %bar2 = alloca <4 x i32>, align 16 + %bar3 = alloca <4 x i32>, align 16 + %bar4 = alloca <4 x i32>, align 16 + store <4 x i32> , ptr %foo, align 16 + %0 = load <4 x i32>, ptr %foo, align 16 + %1 = extractelement <4 x i32> %0, i64 0 + store i32 %1, ptr %z, align 4 + %2 = load <4 x i32>, ptr %foo, align 16 + %3 = load i32, ptr %z, align 4 + %add = add i32 %3, 1 + %elemset = insertelement <4 x i32> %2, i32 %add, i64 2 + store <4 x i32> %elemset, ptr %foo, align 16 + store <4 x i32> zeroinitializer, ptr %bar, align 16 + %4 = load i32, ptr %z, align 4 + %5 = insertelement <4 x i32> , i32 %4, i64 1 + %6 = insertelement <4 x i32> %5, i32 3, i64 2 + %7 = insertelement <4 x i32> %6, i32 4, i64 3 + store <4 x i32> %7, ptr %bar2, align 16 + %8 = load i32, ptr %z, align 4 + %9 = insertelement <4 x i32> zeroinitializer, i32 %8, i64 1 + store <4 x i32> %9, ptr %bar3, align 16 + %10 = load i32, ptr %z, align 4 + %11 = insertelement <4 x i32> zeroinitializer, i32 %10, i64 0 + %12 = insertelement <4 x i32> %11, i32 %10, i64 1 + %13 = insertelement <4 x i32> %12, i32 %10, i64 2 + %14 = insertelement <4 x i32> %13, i32 %10, i64 3 + store <4 x i32> %14, ptr %bar4, align 16 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/vector/vector_ops.c3t b/test/test_suite2/vector/vector_ops.c3t new file mode 100644 index 000000000..4af717e95 --- /dev/null +++ b/test/test_suite2/vector/vector_ops.c3t @@ -0,0 +1,654 @@ +// #target: macos-x64 +import libc; + +fn void testf() +{ + float[<4>] y = { 1, 2, 3, 4 }; + float[<4>] z = { 2, 2, 2, -100 }; + float[<4>] w = y + z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + w = y * z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + w = y / z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + w = y - z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + int[<4>] ww = y < z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y <= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y > z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y >= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y == z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y != z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); +} + +fn void testb() +{ + bool[<4>] y = { true, false, true, true }; + bool[<4>] z = { false, false, true, true }; + ichar[<4>] ww = y < z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y <= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y > z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y >= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y == z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y != z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); +} + +fn void testi() +{ + int[<4>] y = { 1, 2, 3, 4 }; + int[<4>] z = { 2, 2, 2, -100 }; + int[<4>] w = y + z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y * z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y / z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y - z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z >> y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z << y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z > y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z >= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z < y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z <= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z == y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z != y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + uint[<4>] uz = { 2, 6, 2, 1 }; + w = uz > y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz >= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz < y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz <= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz == y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz != y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); +} + +fn void main() +{ + testf(); + testi(); + testb(); +} + +/* #expect: vector_ops.ll + +; Function Attrs: nounwind +define void @vector_ops.testf() #0 { +entry: + %y = alloca <4 x float>, align 16 + %z = alloca <4 x float>, align 16 + %w = alloca <4 x float>, align 16 + %ww = alloca <4 x i32>, align 16 + store <4 x float> , ptr %y, align 16 + store <4 x float> , ptr %z, align 16 + %0 = load <4 x float>, ptr %y, align 16 + %1 = load <4 x float>, ptr %z, align 16 + %fadd = fadd <4 x float> %0, %1 + store <4 x float> %fadd, ptr %w, align 16 + %2 = load <4 x float>, ptr %w, align 16 + %3 = extractelement <4 x float> %2, i64 0 + %fpfpext = fpext float %3 to double + %4 = load <4 x float>, ptr %w, align 16 + %5 = extractelement <4 x float> %4, i64 1 + %fpfpext1 = fpext float %5 to double + %6 = load <4 x float>, ptr %w, align 16 + %7 = extractelement <4 x float> %6, i64 2 + %fpfpext2 = fpext float %7 to double + %8 = load <4 x float>, ptr %w, align 16 + %9 = extractelement <4 x float> %8, i64 3 + %fpfpext3 = fpext float %9 to double + %10 = call i32 (ptr, ...) @printf(ptr @.str, double %fpfpext, double %fpfpext1, double %fpfpext2, double %fpfpext3) + %11 = load <4 x float>, ptr %y, align 16 + %12 = load <4 x float>, ptr %z, align 16 + %fmul = fmul <4 x float> %11, %12 + store <4 x float> %fmul, ptr %w, align 16 + %13 = load <4 x float>, ptr %w, align 16 + %14 = extractelement <4 x float> %13, i64 0 + %fpfpext4 = fpext float %14 to double + %15 = load <4 x float>, ptr %w, align 16 + %16 = extractelement <4 x float> %15, i64 1 + %fpfpext5 = fpext float %16 to double + %17 = load <4 x float>, ptr %w, align 16 + %18 = extractelement <4 x float> %17, i64 2 + %fpfpext6 = fpext float %18 to double + %19 = load <4 x float>, ptr %w, align 16 + %20 = extractelement <4 x float> %19, i64 3 + %fpfpext7 = fpext float %20 to double + %21 = call i32 (ptr, ...) @printf(ptr @.str.1, double %fpfpext4, double %fpfpext5, double %fpfpext6, double %fpfpext7) + %22 = load <4 x float>, ptr %y, align 16 + %23 = load <4 x float>, ptr %z, align 16 + %fdiv = fdiv <4 x float> %22, %23 + store <4 x float> %fdiv, ptr %w, align 16 + %24 = load <4 x float>, ptr %w, align 16 + %25 = extractelement <4 x float> %24, i64 0 + %fpfpext8 = fpext float %25 to double + %26 = load <4 x float>, ptr %w, align 16 + %27 = extractelement <4 x float> %26, i64 1 + %fpfpext9 = fpext float %27 to double + %28 = load <4 x float>, ptr %w, align 16 + %29 = extractelement <4 x float> %28, i64 2 + %fpfpext10 = fpext float %29 to double + %30 = load <4 x float>, ptr %w, align 16 + %31 = extractelement <4 x float> %30, i64 3 + %fpfpext11 = fpext float %31 to double + %32 = call i32 (ptr, ...) @printf(ptr @.str.2, double %fpfpext8, double %fpfpext9, double %fpfpext10, double %fpfpext11) + %33 = load <4 x float>, ptr %y, align 16 + %34 = load <4 x float>, ptr %z, align 16 + %fsub = fsub <4 x float> %33, %34 + store <4 x float> %fsub, ptr %w, align 16 + %35 = load <4 x float>, ptr %w, align 16 + %36 = extractelement <4 x float> %35, i64 0 + %fpfpext12 = fpext float %36 to double + %37 = load <4 x float>, ptr %w, align 16 + %38 = extractelement <4 x float> %37, i64 1 + %fpfpext13 = fpext float %38 to double + %39 = load <4 x float>, ptr %w, align 16 + %40 = extractelement <4 x float> %39, i64 2 + %fpfpext14 = fpext float %40 to double + %41 = load <4 x float>, ptr %w, align 16 + %42 = extractelement <4 x float> %41, i64 3 + %fpfpext15 = fpext float %42 to double + %43 = call i32 (ptr, ...) @printf(ptr @.str.3, double %fpfpext12, double %fpfpext13, double %fpfpext14, double %fpfpext15) + %44 = load <4 x float>, ptr %y, align 16 + %45 = load <4 x float>, ptr %z, align 16 + %lt = fcmp olt <4 x float> %44, %45 + %46 = sext <4 x i1> %lt to <4 x i32> + store <4 x i32> %46, ptr %ww, align 16 + %47 = load <4 x i32>, ptr %ww, align 16 + %48 = extractelement <4 x i32> %47, i64 0 + %49 = load <4 x i32>, ptr %ww, align 16 + %50 = extractelement <4 x i32> %49, i64 1 + %51 = load <4 x i32>, ptr %ww, align 16 + %52 = extractelement <4 x i32> %51, i64 2 + %53 = load <4 x i32>, ptr %ww, align 16 + %54 = extractelement <4 x i32> %53, i64 3 + %55 = call i32 (ptr, ...) @printf(ptr @.str.4, i32 %48, i32 %50, i32 %52, i32 %54) + %56 = load <4 x float>, ptr %y, align 16 + %57 = load <4 x float>, ptr %z, align 16 + %le = fcmp ole <4 x float> %56, %57 + %58 = sext <4 x i1> %le to <4 x i32> + store <4 x i32> %58, ptr %ww, align 16 + %59 = load <4 x i32>, ptr %ww, align 16 + %60 = extractelement <4 x i32> %59, i64 0 + %61 = load <4 x i32>, ptr %ww, align 16 + %62 = extractelement <4 x i32> %61, i64 1 + %63 = load <4 x i32>, ptr %ww, align 16 + %64 = extractelement <4 x i32> %63, i64 2 + %65 = load <4 x i32>, ptr %ww, align 16 + %66 = extractelement <4 x i32> %65, i64 3 + %67 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %60, i32 %62, i32 %64, i32 %66) + %68 = load <4 x float>, ptr %y, align 16 + %69 = load <4 x float>, ptr %z, align 16 + %gt = fcmp ogt <4 x float> %68, %69 + %70 = sext <4 x i1> %gt to <4 x i32> + store <4 x i32> %70, ptr %ww, align 16 + %71 = load <4 x i32>, ptr %ww, align 16 + %72 = extractelement <4 x i32> %71, i64 0 + %73 = load <4 x i32>, ptr %ww, align 16 + %74 = extractelement <4 x i32> %73, i64 1 + %75 = load <4 x i32>, ptr %ww, align 16 + %76 = extractelement <4 x i32> %75, i64 2 + %77 = load <4 x i32>, ptr %ww, align 16 + %78 = extractelement <4 x i32> %77, i64 3 + %79 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %72, i32 %74, i32 %76, i32 %78) + %80 = load <4 x float>, ptr %y, align 16 + %81 = load <4 x float>, ptr %z, align 16 + %ge = fcmp oge <4 x float> %80, %81 + %82 = sext <4 x i1> %ge to <4 x i32> + store <4 x i32> %82, ptr %ww, align 16 + %83 = load <4 x i32>, ptr %ww, align 16 + %84 = extractelement <4 x i32> %83, i64 0 + %85 = load <4 x i32>, ptr %ww, align 16 + %86 = extractelement <4 x i32> %85, i64 1 + %87 = load <4 x i32>, ptr %ww, align 16 + %88 = extractelement <4 x i32> %87, i64 2 + %89 = load <4 x i32>, ptr %ww, align 16 + %90 = extractelement <4 x i32> %89, i64 3 + %91 = call i32 (ptr, ...) @printf(ptr @.str.7, i32 %84, i32 %86, i32 %88, i32 %90) + %92 = load <4 x float>, ptr %y, align 16 + %93 = load <4 x float>, ptr %z, align 16 + %eq = fcmp oeq <4 x float> %92, %93 + %94 = sext <4 x i1> %eq to <4 x i32> + store <4 x i32> %94, ptr %ww, align 16 + %95 = load <4 x i32>, ptr %ww, align 16 + %96 = extractelement <4 x i32> %95, i64 0 + %97 = load <4 x i32>, ptr %ww, align 16 + %98 = extractelement <4 x i32> %97, i64 1 + %99 = load <4 x i32>, ptr %ww, align 16 + %100 = extractelement <4 x i32> %99, i64 2 + %101 = load <4 x i32>, ptr %ww, align 16 + %102 = extractelement <4 x i32> %101, i64 3 + %103 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %96, i32 %98, i32 %100, i32 %102) + %104 = load <4 x float>, ptr %y, align 16 + %105 = load <4 x float>, ptr %z, align 16 + %neq = fcmp one <4 x float> %104, %105 + %106 = sext <4 x i1> %neq to <4 x i32> + store <4 x i32> %106, ptr %ww, align 16 + %107 = load <4 x i32>, ptr %ww, align 16 + %108 = extractelement <4 x i32> %107, i64 0 + %109 = load <4 x i32>, ptr %ww, align 16 + %110 = extractelement <4 x i32> %109, i64 1 + %111 = load <4 x i32>, ptr %ww, align 16 + %112 = extractelement <4 x i32> %111, i64 2 + %113 = load <4 x i32>, ptr %ww, align 16 + %114 = extractelement <4 x i32> %113, i64 3 + %115 = call i32 (ptr, ...) @printf(ptr @.str.9, i32 %108, i32 %110, i32 %112, i32 %114) + ret void +} + + +define void @vector_ops.testb() #0 { +entry: + %y = alloca <4 x i8>, align 4 + %z = alloca <4 x i8>, align 4 + %ww = alloca <4 x i8>, align 4 + store <4 x i8> , ptr %y, align 4 + store <4 x i8> , ptr %z, align 4 + %0 = load <4 x i8>, ptr %y, align 4 + %1 = load <4 x i8>, ptr %z, align 4 + %lt = icmp ult <4 x i8> %0, %1 + %2 = sext <4 x i1> %lt to <4 x i8> + store <4 x i8> %2, ptr %ww, align 4 + %3 = load <4 x i8>, ptr %ww, align 4 + %4 = extractelement <4 x i8> %3, i64 0 + %sisiext = sext i8 %4 to i32 + %5 = load <4 x i8>, ptr %ww, align 4 + %6 = extractelement <4 x i8> %5, i64 1 + %sisiext1 = sext i8 %6 to i32 + %7 = load <4 x i8>, ptr %ww, align 4 + %8 = extractelement <4 x i8> %7, i64 2 + %sisiext2 = sext i8 %8 to i32 + %9 = load <4 x i8>, ptr %ww, align 4 + %10 = extractelement <4 x i8> %9, i64 3 + %sisiext3 = sext i8 %10 to i32 + %11 = call i32 (ptr, ...) @printf(ptr @.str.10, i32 %sisiext, i32 %sisiext1, i32 %sisiext2, i32 %sisiext3) + %12 = load <4 x i8>, ptr %y, align 4 + %13 = load <4 x i8>, ptr %z, align 4 + %le = icmp ule <4 x i8> %12, %13 + %14 = sext <4 x i1> %le to <4 x i8> + store <4 x i8> %14, ptr %ww, align 4 + %15 = load <4 x i8>, ptr %ww, align 4 + %16 = extractelement <4 x i8> %15, i64 0 + %sisiext4 = sext i8 %16 to i32 + %17 = load <4 x i8>, ptr %ww, align 4 + %18 = extractelement <4 x i8> %17, i64 1 + %sisiext5 = sext i8 %18 to i32 + %19 = load <4 x i8>, ptr %ww, align 4 + %20 = extractelement <4 x i8> %19, i64 2 + %sisiext6 = sext i8 %20 to i32 + %21 = load <4 x i8>, ptr %ww, align 4 + %22 = extractelement <4 x i8> %21, i64 3 + %sisiext7 = sext i8 %22 to i32 + %23 = call i32 (ptr, ...) @printf(ptr @.str.11, i32 %sisiext4, i32 %sisiext5, i32 %sisiext6, i32 %sisiext7) + %24 = load <4 x i8>, ptr %y, align 4 + %25 = load <4 x i8>, ptr %z, align 4 + %gt = icmp ugt <4 x i8> %24, %25 + %26 = sext <4 x i1> %gt to <4 x i8> + store <4 x i8> %26, ptr %ww, align 4 + %27 = load <4 x i8>, ptr %ww, align 4 + %28 = extractelement <4 x i8> %27, i64 0 + %sisiext8 = sext i8 %28 to i32 + %29 = load <4 x i8>, ptr %ww, align 4 + %30 = extractelement <4 x i8> %29, i64 1 + %sisiext9 = sext i8 %30 to i32 + %31 = load <4 x i8>, ptr %ww, align 4 + %32 = extractelement <4 x i8> %31, i64 2 + %sisiext10 = sext i8 %32 to i32 + %33 = load <4 x i8>, ptr %ww, align 4 + %34 = extractelement <4 x i8> %33, i64 3 + %sisiext11 = sext i8 %34 to i32 + %35 = call i32 (ptr, ...) @printf(ptr @.str.12, i32 %sisiext8, i32 %sisiext9, i32 %sisiext10, i32 %sisiext11) + %36 = load <4 x i8>, ptr %y, align 4 + %37 = load <4 x i8>, ptr %z, align 4 + %ge = icmp uge <4 x i8> %36, %37 + %38 = sext <4 x i1> %ge to <4 x i8> + store <4 x i8> %38, ptr %ww, align 4 + %39 = load <4 x i8>, ptr %ww, align 4 + %40 = extractelement <4 x i8> %39, i64 0 + %sisiext12 = sext i8 %40 to i32 + %41 = load <4 x i8>, ptr %ww, align 4 + %42 = extractelement <4 x i8> %41, i64 1 + %sisiext13 = sext i8 %42 to i32 + %43 = load <4 x i8>, ptr %ww, align 4 + %44 = extractelement <4 x i8> %43, i64 2 + %sisiext14 = sext i8 %44 to i32 + %45 = load <4 x i8>, ptr %ww, align 4 + %46 = extractelement <4 x i8> %45, i64 3 + %sisiext15 = sext i8 %46 to i32 + %47 = call i32 (ptr, ...) @printf(ptr @.str.13, i32 %sisiext12, i32 %sisiext13, i32 %sisiext14, i32 %sisiext15) + %48 = load <4 x i8>, ptr %y, align 4 + %49 = load <4 x i8>, ptr %z, align 4 + %eq = icmp eq <4 x i8> %48, %49 + %50 = sext <4 x i1> %eq to <4 x i8> + store <4 x i8> %50, ptr %ww, align 4 + %51 = load <4 x i8>, ptr %ww, align 4 + %52 = extractelement <4 x i8> %51, i64 0 + %sisiext16 = sext i8 %52 to i32 + %53 = load <4 x i8>, ptr %ww, align 4 + %54 = extractelement <4 x i8> %53, i64 1 + %sisiext17 = sext i8 %54 to i32 + %55 = load <4 x i8>, ptr %ww, align 4 + %56 = extractelement <4 x i8> %55, i64 2 + %sisiext18 = sext i8 %56 to i32 + %57 = load <4 x i8>, ptr %ww, align 4 + %58 = extractelement <4 x i8> %57, i64 3 + %sisiext19 = sext i8 %58 to i32 + %59 = call i32 (ptr, ...) @printf(ptr @.str.14, i32 %sisiext16, i32 %sisiext17, i32 %sisiext18, i32 %sisiext19) + %60 = load <4 x i8>, ptr %y, align 4 + %61 = load <4 x i8>, ptr %z, align 4 + %neq = icmp ne <4 x i8> %60, %61 + %62 = sext <4 x i1> %neq to <4 x i8> + store <4 x i8> %62, ptr %ww, align 4 + %63 = load <4 x i8>, ptr %ww, align 4 + %64 = extractelement <4 x i8> %63, i64 0 + %sisiext20 = sext i8 %64 to i32 + %65 = load <4 x i8>, ptr %ww, align 4 + %66 = extractelement <4 x i8> %65, i64 1 + %sisiext21 = sext i8 %66 to i32 + %67 = load <4 x i8>, ptr %ww, align 4 + %68 = extractelement <4 x i8> %67, i64 2 + %sisiext22 = sext i8 %68 to i32 + %69 = load <4 x i8>, ptr %ww, align 4 + %70 = extractelement <4 x i8> %69, i64 3 + %sisiext23 = sext i8 %70 to i32 + %71 = call i32 (ptr, ...) @printf(ptr @.str.15, i32 %sisiext20, i32 %sisiext21, i32 %sisiext22, i32 %sisiext23) + ret void +} + +; Function Attrs: nounwind +define void @vector_ops.testi() #0 { +entry: + %y = alloca <4 x i32>, align 16 + %z = alloca <4 x i32>, align 16 + %w = alloca <4 x i32>, align 16 + %uz = alloca <4 x i32>, align 16 + store <4 x i32> , ptr %y, align 16 + store <4 x i32> , ptr %z, align 16 + %0 = load <4 x i32>, ptr %y, align 16 + %1 = load <4 x i32>, ptr %z, align 16 + %add = add <4 x i32> %0, %1 + store <4 x i32> %add, ptr %w, align 16 + %2 = load <4 x i32>, ptr %w, align 16 + %3 = extractelement <4 x i32> %2, i64 0 + %4 = load <4 x i32>, ptr %w, align 16 + %5 = extractelement <4 x i32> %4, i64 1 + %6 = load <4 x i32>, ptr %w, align 16 + %7 = extractelement <4 x i32> %6, i64 2 + %8 = load <4 x i32>, ptr %w, align 16 + %9 = extractelement <4 x i32> %8, i64 3 + %10 = call i32 (ptr, ...) @printf(ptr @.str.16, i32 %3, i32 %5, i32 %7, i32 %9) + %11 = load <4 x i32>, ptr %y, align 16 + %12 = load <4 x i32>, ptr %z, align 16 + %mul = mul <4 x i32> %11, %12 + store <4 x i32> %mul, ptr %w, align 16 + %13 = load <4 x i32>, ptr %w, align 16 + %14 = extractelement <4 x i32> %13, i64 0 + %15 = load <4 x i32>, ptr %w, align 16 + %16 = extractelement <4 x i32> %15, i64 1 + %17 = load <4 x i32>, ptr %w, align 16 + %18 = extractelement <4 x i32> %17, i64 2 + %19 = load <4 x i32>, ptr %w, align 16 + %20 = extractelement <4 x i32> %19, i64 3 + %21 = call i32 (ptr, ...) @printf(ptr @.str.17, i32 %14, i32 %16, i32 %18, i32 %20) + %22 = load <4 x i32>, ptr %y, align 16 + %23 = load <4 x i32>, ptr %z, align 16 + %sdiv = sdiv <4 x i32> %22, %23 + store <4 x i32> %sdiv, ptr %w, align 16 + %24 = load <4 x i32>, ptr %w, align 16 + %25 = extractelement <4 x i32> %24, i64 0 + %26 = load <4 x i32>, ptr %w, align 16 + %27 = extractelement <4 x i32> %26, i64 1 + %28 = load <4 x i32>, ptr %w, align 16 + %29 = extractelement <4 x i32> %28, i64 2 + %30 = load <4 x i32>, ptr %w, align 16 + %31 = extractelement <4 x i32> %30, i64 3 + %32 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %25, i32 %27, i32 %29, i32 %31) + %33 = load <4 x i32>, ptr %y, align 16 + %34 = load <4 x i32>, ptr %z, align 16 + %sub = sub <4 x i32> %33, %34 + store <4 x i32> %sub, ptr %w, align 16 + %35 = load <4 x i32>, ptr %w, align 16 + %36 = extractelement <4 x i32> %35, i64 0 + %37 = load <4 x i32>, ptr %w, align 16 + %38 = extractelement <4 x i32> %37, i64 1 + %39 = load <4 x i32>, ptr %w, align 16 + %40 = extractelement <4 x i32> %39, i64 2 + %41 = load <4 x i32>, ptr %w, align 16 + %42 = extractelement <4 x i32> %41, i64 3 + %43 = call i32 (ptr, ...) @printf(ptr @.str.19, i32 %36, i32 %38, i32 %40, i32 %42) + %44 = load <4 x i32>, ptr %z, align 16 + %45 = load <4 x i32>, ptr %y, align 16 + %ashr = ashr <4 x i32> %44, %45 + %46 = freeze <4 x i32> %ashr + store <4 x i32> %46, ptr %w, align 16 + %47 = load <4 x i32>, ptr %w, align 16 + %48 = extractelement <4 x i32> %47, i64 0 + %49 = load <4 x i32>, ptr %w, align 16 + %50 = extractelement <4 x i32> %49, i64 1 + %51 = load <4 x i32>, ptr %w, align 16 + %52 = extractelement <4 x i32> %51, i64 2 + %53 = load <4 x i32>, ptr %w, align 16 + %54 = extractelement <4 x i32> %53, i64 3 + %55 = call i32 (ptr, ...) @printf(ptr @.str.20, i32 %48, i32 %50, i32 %52, i32 %54) + %56 = load <4 x i32>, ptr %z, align 16 + %57 = load <4 x i32>, ptr %y, align 16 + %shl = shl <4 x i32> %56, %57 + %58 = freeze <4 x i32> %shl + store <4 x i32> %58, ptr %w, align 16 + %59 = load <4 x i32>, ptr %w, align 16 + %60 = extractelement <4 x i32> %59, i64 0 + %61 = load <4 x i32>, ptr %w, align 16 + %62 = extractelement <4 x i32> %61, i64 1 + %63 = load <4 x i32>, ptr %w, align 16 + %64 = extractelement <4 x i32> %63, i64 2 + %65 = load <4 x i32>, ptr %w, align 16 + %66 = extractelement <4 x i32> %65, i64 3 + %67 = call i32 (ptr, ...) @printf(ptr @.str.21, i32 %60, i32 %62, i32 %64, i32 %66) + %68 = load <4 x i32>, ptr %z, align 16 + %69 = load <4 x i32>, ptr %y, align 16 + %gt = icmp sgt <4 x i32> %68, %69 + %70 = sext <4 x i1> %gt to <4 x i32> + store <4 x i32> %70, ptr %w, align 16 + %71 = load <4 x i32>, ptr %w, align 16 + %72 = extractelement <4 x i32> %71, i64 0 + %73 = load <4 x i32>, ptr %w, align 16 + %74 = extractelement <4 x i32> %73, i64 1 + %75 = load <4 x i32>, ptr %w, align 16 + %76 = extractelement <4 x i32> %75, i64 2 + %77 = load <4 x i32>, ptr %w, align 16 + %78 = extractelement <4 x i32> %77, i64 3 + %79 = call i32 (ptr, ...) @printf(ptr @.str.22, i32 %72, i32 %74, i32 %76, i32 %78) + %80 = load <4 x i32>, ptr %z, align 16 + %81 = load <4 x i32>, ptr %y, align 16 + %ge = icmp sge <4 x i32> %80, %81 + %82 = sext <4 x i1> %ge to <4 x i32> + store <4 x i32> %82, ptr %w, align 16 + %83 = load <4 x i32>, ptr %w, align 16 + %84 = extractelement <4 x i32> %83, i64 0 + %85 = load <4 x i32>, ptr %w, align 16 + %86 = extractelement <4 x i32> %85, i64 1 + %87 = load <4 x i32>, ptr %w, align 16 + %88 = extractelement <4 x i32> %87, i64 2 + %89 = load <4 x i32>, ptr %w, align 16 + %90 = extractelement <4 x i32> %89, i64 3 + %91 = call i32 (ptr, ...) @printf(ptr @.str.23, i32 %84, i32 %86, i32 %88, i32 %90) + %92 = load <4 x i32>, ptr %z, align 16 + %93 = load <4 x i32>, ptr %y, align 16 + %lt = icmp slt <4 x i32> %92, %93 + %94 = sext <4 x i1> %lt to <4 x i32> + store <4 x i32> %94, ptr %w, align 16 + %95 = load <4 x i32>, ptr %w, align 16 + %96 = extractelement <4 x i32> %95, i64 0 + %97 = load <4 x i32>, ptr %w, align 16 + %98 = extractelement <4 x i32> %97, i64 1 + %99 = load <4 x i32>, ptr %w, align 16 + %100 = extractelement <4 x i32> %99, i64 2 + %101 = load <4 x i32>, ptr %w, align 16 + %102 = extractelement <4 x i32> %101, i64 3 + %103 = call i32 (ptr, ...) @printf(ptr @.str.24, i32 %96, i32 %98, i32 %100, i32 %102) + %104 = load <4 x i32>, ptr %z, align 16 + %105 = load <4 x i32>, ptr %y, align 16 + %le = icmp sle <4 x i32> %104, %105 + %106 = sext <4 x i1> %le to <4 x i32> + store <4 x i32> %106, ptr %w, align 16 + %107 = load <4 x i32>, ptr %w, align 16 + %108 = extractelement <4 x i32> %107, i64 0 + %109 = load <4 x i32>, ptr %w, align 16 + %110 = extractelement <4 x i32> %109, i64 1 + %111 = load <4 x i32>, ptr %w, align 16 + %112 = extractelement <4 x i32> %111, i64 2 + %113 = load <4 x i32>, ptr %w, align 16 + %114 = extractelement <4 x i32> %113, i64 3 + %115 = call i32 (ptr, ...) @printf(ptr @.str.25, i32 %108, i32 %110, i32 %112, i32 %114) + %116 = load <4 x i32>, ptr %z, align 16 + %117 = load <4 x i32>, ptr %y, align 16 + %eq = icmp eq <4 x i32> %116, %117 + %118 = sext <4 x i1> %eq to <4 x i32> + store <4 x i32> %118, ptr %w, align 16 + %119 = load <4 x i32>, ptr %w, align 16 + %120 = extractelement <4 x i32> %119, i64 0 + %121 = load <4 x i32>, ptr %w, align 16 + %122 = extractelement <4 x i32> %121, i64 1 + %123 = load <4 x i32>, ptr %w, align 16 + %124 = extractelement <4 x i32> %123, i64 2 + %125 = load <4 x i32>, ptr %w, align 16 + %126 = extractelement <4 x i32> %125, i64 3 + %127 = call i32 (ptr, ...) @printf(ptr @.str.26, i32 %120, i32 %122, i32 %124, i32 %126) + %128 = load <4 x i32>, ptr %z, align 16 + %129 = load <4 x i32>, ptr %y, align 16 + %neq = icmp ne <4 x i32> %128, %129 + %130 = sext <4 x i1> %neq to <4 x i32> + store <4 x i32> %130, ptr %w, align 16 + %131 = load <4 x i32>, ptr %w, align 16 + %132 = extractelement <4 x i32> %131, i64 0 + %133 = load <4 x i32>, ptr %w, align 16 + %134 = extractelement <4 x i32> %133, i64 1 + %135 = load <4 x i32>, ptr %w, align 16 + %136 = extractelement <4 x i32> %135, i64 2 + %137 = load <4 x i32>, ptr %w, align 16 + %138 = extractelement <4 x i32> %137, i64 3 + %139 = call i32 (ptr, ...) @printf(ptr @.str.27, i32 %132, i32 %134, i32 %136, i32 %138) + store <4 x i32> , ptr %uz, align 16 + %140 = load <4 x i32>, ptr %uz, align 16 + %141 = load <4 x i32>, ptr %y, align 16 + %lt1 = icmp slt <4 x i32> %141, %140 + %check = icmp slt <4 x i32> %140, zeroinitializer + %siui-lt = or <4 x i1> %check, %lt1 + %142 = sext <4 x i1> %siui-lt to <4 x i32> + store <4 x i32> %142, ptr %w, align 16 + %143 = load <4 x i32>, ptr %w, align 16 + %144 = extractelement <4 x i32> %143, i64 0 + %145 = load <4 x i32>, ptr %w, align 16 + %146 = extractelement <4 x i32> %145, i64 1 + %147 = load <4 x i32>, ptr %w, align 16 + %148 = extractelement <4 x i32> %147, i64 2 + %149 = load <4 x i32>, ptr %w, align 16 + %150 = extractelement <4 x i32> %149, i64 3 + %151 = call i32 (ptr, ...) @printf(ptr @.str.28, i32 %144, i32 %146, i32 %148, i32 %150) + %152 = load <4 x i32>, ptr %uz, align 16 + %153 = load <4 x i32>, ptr %y, align 16 + %le2 = icmp sle <4 x i32> %153, %152 + %check3 = icmp slt <4 x i32> %152, zeroinitializer + %siui-le = or <4 x i1> %check3, %le2 + %154 = sext <4 x i1> %siui-le to <4 x i32> + store <4 x i32> %154, ptr %w, align 16 + %155 = load <4 x i32>, ptr %w, align 16 + %156 = extractelement <4 x i32> %155, i64 0 + %157 = load <4 x i32>, ptr %w, align 16 + %158 = extractelement <4 x i32> %157, i64 1 + %159 = load <4 x i32>, ptr %w, align 16 + %160 = extractelement <4 x i32> %159, i64 2 + %161 = load <4 x i32>, ptr %w, align 16 + %162 = extractelement <4 x i32> %161, i64 3 + %163 = call i32 (ptr, ...) @printf(ptr @.str.29, i32 %156, i32 %158, i32 %160, i32 %162) + %164 = load <4 x i32>, ptr %uz, align 16 + %165 = load <4 x i32>, ptr %y, align 16 + %gt4 = icmp sgt <4 x i32> %165, %164 + %check5 = icmp sge <4 x i32> %164, zeroinitializer + %siui-gt = and <4 x i1> %check5, %gt4 + %166 = sext <4 x i1> %siui-gt to <4 x i32> + store <4 x i32> %166, ptr %w, align 16 + %167 = load <4 x i32>, ptr %w, align 16 + %168 = extractelement <4 x i32> %167, i64 0 + %169 = load <4 x i32>, ptr %w, align 16 + %170 = extractelement <4 x i32> %169, i64 1 + %171 = load <4 x i32>, ptr %w, align 16 + %172 = extractelement <4 x i32> %171, i64 2 + %173 = load <4 x i32>, ptr %w, align 16 + %174 = extractelement <4 x i32> %173, i64 3 + %175 = call i32 (ptr, ...) @printf(ptr @.str.30, i32 %168, i32 %170, i32 %172, i32 %174) + %176 = load <4 x i32>, ptr %uz, align 16 + %177 = load <4 x i32>, ptr %y, align 16 + %ge6 = icmp sge <4 x i32> %177, %176 + %check7 = icmp sge <4 x i32> %176, zeroinitializer + %siui-ge = and <4 x i1> %check7, %ge6 + %178 = sext <4 x i1> %siui-ge to <4 x i32> + store <4 x i32> %178, ptr %w, align 16 + %179 = load <4 x i32>, ptr %w, align 16 + %180 = extractelement <4 x i32> %179, i64 0 + %181 = load <4 x i32>, ptr %w, align 16 + %182 = extractelement <4 x i32> %181, i64 1 + %183 = load <4 x i32>, ptr %w, align 16 + %184 = extractelement <4 x i32> %183, i64 2 + %185 = load <4 x i32>, ptr %w, align 16 + %186 = extractelement <4 x i32> %185, i64 3 + %187 = call i32 (ptr, ...) @printf(ptr @.str.31, i32 %180, i32 %182, i32 %184, i32 %186) + %188 = load <4 x i32>, ptr %uz, align 16 + %189 = load <4 x i32>, ptr %y, align 16 + %eq8 = icmp eq <4 x i32> %189, %188 + %check9 = icmp sge <4 x i32> %189, zeroinitializer + %siui-eq = and <4 x i1> %check9, %eq8 + %190 = sext <4 x i1> %siui-eq to <4 x i32> + store <4 x i32> %190, ptr %w, align 16 + %191 = load <4 x i32>, ptr %w, align 16 + %192 = extractelement <4 x i32> %191, i64 0 + %193 = load <4 x i32>, ptr %w, align 16 + %194 = extractelement <4 x i32> %193, i64 1 + %195 = load <4 x i32>, ptr %w, align 16 + %196 = extractelement <4 x i32> %195, i64 2 + %197 = load <4 x i32>, ptr %w, align 16 + %198 = extractelement <4 x i32> %197, i64 3 + %199 = call i32 (ptr, ...) @printf(ptr @.str.32, i32 %192, i32 %194, i32 %196, i32 %198) + %200 = load <4 x i32>, ptr %uz, align 16 + %201 = load <4 x i32>, ptr %y, align 16 + %neq10 = icmp ne <4 x i32> %201, %200 + %check11 = icmp slt <4 x i32> %201, zeroinitializer + %siui-ne = or <4 x i1> %check11, %neq10 + %202 = sext <4 x i1> %siui-ne to <4 x i32> + store <4 x i32> %202, ptr %w, align 16 + %203 = load <4 x i32>, ptr %w, align 16 + %204 = extractelement <4 x i32> %203, i64 0 + %205 = load <4 x i32>, ptr %w, align 16 + %206 = extractelement <4 x i32> %205, i64 1 + %207 = load <4 x i32>, ptr %w, align 16 + %208 = extractelement <4 x i32> %207, i64 2 + %209 = load <4 x i32>, ptr %w, align 16 + %210 = extractelement <4 x i32> %209, i64 3 + %211 = call i32 (ptr, ...) @printf(ptr @.str.33, i32 %204, i32 %206, i32 %208, i32 %210) + ret void +} \ No newline at end of file diff --git a/test/test_suite2/vector/vector_ops2.c3t b/test/test_suite2/vector/vector_ops2.c3t new file mode 100644 index 000000000..6d280827a --- /dev/null +++ b/test/test_suite2/vector/vector_ops2.c3t @@ -0,0 +1,710 @@ +// #target: macos-x64 +// #safe: yes +module test; +import libc; + +fn void testf() +{ + float[<4>] y = { 1, 2, 3, 4 }; + float[<4>] z = { 2, 2, 2, -100 }; + float[<4>] w = y + z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + w = y * z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + w = y / z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + w = y - z; + libc::printf("%f %f %f %f\n", w[0], w[1], w[2], w[3]); + int[<4>] ww = y < z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y <= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y > z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y >= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y == z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y != z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); +} + +fn void testb() +{ + bool[<4>] y = { true, false, true, true }; + bool[<4>] z = { false, false, true, true }; + ichar[<4>] ww = y < z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y <= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y > z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y >= z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y == z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); + ww = y != z; + libc::printf("%d %d %d %d\n", ww[0], ww[1], ww[2], ww[3]); +} + +fn void testi() +{ + int[<4>] y = { 1, 2, 3, 4 }; + int[<4>] z = { 2, 2, 2, -100 }; + int[<4>] w = y + z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y * z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y / z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = y - z; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z >> y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z << y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z > y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z >= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z < y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z <= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z == y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = z != y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + uint[<4>] uz = { 2, 6, 2, 1 }; + w = uz > y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz >= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz < y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz <= y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz == y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); + w = uz != y; + libc::printf("%d %d %d %d\n", w[0], w[1], w[2], w[3]); +} + +fn void main() +{ + testf(); + testi(); + testb(); +} + +/* #expect: test.ll + +define void @test.testf() #0 { +entry: + %y = alloca <4 x float>, align 16 + %z = alloca <4 x float>, align 16 + %w = alloca <4 x float>, align 16 + %ww = alloca <4 x i32>, align 16 + store <4 x float> , ptr %y, align 16 + store <4 x float> , ptr %z, align 16 + %0 = load <4 x float>, ptr %y, align 16 + %1 = load <4 x float>, ptr %z, align 16 + %fadd = fadd <4 x float> %0, %1 + store <4 x float> %fadd, ptr %w, align 16 + %2 = load <4 x float>, ptr %w, align 16 + %3 = extractelement <4 x float> %2, i64 0 + %fpfpext = fpext float %3 to double + %4 = load <4 x float>, ptr %w, align 16 + %5 = extractelement <4 x float> %4, i64 1 + %fpfpext1 = fpext float %5 to double + %6 = load <4 x float>, ptr %w, align 16 + %7 = extractelement <4 x float> %6, i64 2 + %fpfpext2 = fpext float %7 to double + %8 = load <4 x float>, ptr %w, align 16 + %9 = extractelement <4 x float> %8, i64 3 + %fpfpext3 = fpext float %9 to double + %10 = call i32 (ptr, ...) @printf(ptr @.str, double %fpfpext, double %fpfpext1, double %fpfpext2, double %fpfpext3) + %11 = load <4 x float>, ptr %y, align 16 + %12 = load <4 x float>, ptr %z, align 16 + %fmul = fmul <4 x float> %11, %12 + store <4 x float> %fmul, ptr %w, align 16 + %13 = load <4 x float>, ptr %w, align 16 + %14 = extractelement <4 x float> %13, i64 0 + %fpfpext4 = fpext float %14 to double + %15 = load <4 x float>, ptr %w, align 16 + %16 = extractelement <4 x float> %15, i64 1 + %fpfpext5 = fpext float %16 to double + %17 = load <4 x float>, ptr %w, align 16 + %18 = extractelement <4 x float> %17, i64 2 + %fpfpext6 = fpext float %18 to double + %19 = load <4 x float>, ptr %w, align 16 + %20 = extractelement <4 x float> %19, i64 3 + %fpfpext7 = fpext float %20 to double + %21 = call i32 (ptr, ...) @printf(ptr @.str.1, double %fpfpext4, double %fpfpext5, double %fpfpext6, double %fpfpext7) + %22 = load <4 x float>, ptr %y, align 16 + %23 = load <4 x float>, ptr %z, align 16 + %24 = call <4 x float> @llvm.fabs.v4f32(<4 x float> %23) + %25 = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> %24) + %zero = fcmp ueq float %25, 0.000000e+00 + br i1 %zero, label %panic, label %checkok + +panic: ; preds = %entry + call void @"std::core::builtin.panic"(ptr @.zstr, ptr @.zstr.2, ptr @.zstr.3, i32 12) + br label %checkok + +checkok: ; preds = %panic, %entry + %fdiv = fdiv <4 x float> %22, %23 + store <4 x float> %fdiv, ptr %w, align 16 + %26 = load <4 x float>, ptr %w, align 16 + %27 = extractelement <4 x float> %26, i64 0 + %fpfpext8 = fpext float %27 to double + %28 = load <4 x float>, ptr %w, align 16 + %29 = extractelement <4 x float> %28, i64 1 + %fpfpext9 = fpext float %29 to double + %30 = load <4 x float>, ptr %w, align 16 + %31 = extractelement <4 x float> %30, i64 2 + %fpfpext10 = fpext float %31 to double + %32 = load <4 x float>, ptr %w, align 16 + %33 = extractelement <4 x float> %32, i64 3 + %fpfpext11 = fpext float %33 to double + %34 = call i32 (ptr, ...) @printf(ptr @.str.4, double %fpfpext8, double %fpfpext9, double %fpfpext10, double %fpfpext11) + %35 = load <4 x float>, ptr %y, align 16 + %36 = load <4 x float>, ptr %z, align 16 + %fsub = fsub <4 x float> %35, %36 + store <4 x float> %fsub, ptr %w, align 16 + %37 = load <4 x float>, ptr %w, align 16 + %38 = extractelement <4 x float> %37, i64 0 + %fpfpext12 = fpext float %38 to double + %39 = load <4 x float>, ptr %w, align 16 + %40 = extractelement <4 x float> %39, i64 1 + %fpfpext13 = fpext float %40 to double + %41 = load <4 x float>, ptr %w, align 16 + %42 = extractelement <4 x float> %41, i64 2 + %fpfpext14 = fpext float %42 to double + %43 = load <4 x float>, ptr %w, align 16 + %44 = extractelement <4 x float> %43, i64 3 + %fpfpext15 = fpext float %44 to double + %45 = call i32 (ptr, ...) @printf(ptr @.str.5, double %fpfpext12, double %fpfpext13, double %fpfpext14, double %fpfpext15) + %46 = load <4 x float>, ptr %y, align 16 + %47 = load <4 x float>, ptr %z, align 16 + %lt = fcmp olt <4 x float> %46, %47 + %48 = sext <4 x i1> %lt to <4 x i32> + store <4 x i32> %48, ptr %ww, align 16 + %49 = load <4 x i32>, ptr %ww, align 16 + %50 = extractelement <4 x i32> %49, i64 0 + %51 = load <4 x i32>, ptr %ww, align 16 + %52 = extractelement <4 x i32> %51, i64 1 + %53 = load <4 x i32>, ptr %ww, align 16 + %54 = extractelement <4 x i32> %53, i64 2 + %55 = load <4 x i32>, ptr %ww, align 16 + %56 = extractelement <4 x i32> %55, i64 3 + %57 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %50, i32 %52, i32 %54, i32 %56) + %58 = load <4 x float>, ptr %y, align 16 + %59 = load <4 x float>, ptr %z, align 16 + %le = fcmp ole <4 x float> %58, %59 + %60 = sext <4 x i1> %le to <4 x i32> + store <4 x i32> %60, ptr %ww, align 16 + %61 = load <4 x i32>, ptr %ww, align 16 + %62 = extractelement <4 x i32> %61, i64 0 + %63 = load <4 x i32>, ptr %ww, align 16 + %64 = extractelement <4 x i32> %63, i64 1 + %65 = load <4 x i32>, ptr %ww, align 16 + %66 = extractelement <4 x i32> %65, i64 2 + %67 = load <4 x i32>, ptr %ww, align 16 + %68 = extractelement <4 x i32> %67, i64 3 + %69 = call i32 (ptr, ...) @printf(ptr @.str.7, i32 %62, i32 %64, i32 %66, i32 %68) + %70 = load <4 x float>, ptr %y, align 16 + %71 = load <4 x float>, ptr %z, align 16 + %gt = fcmp ogt <4 x float> %70, %71 + %72 = sext <4 x i1> %gt to <4 x i32> + store <4 x i32> %72, ptr %ww, align 16 + %73 = load <4 x i32>, ptr %ww, align 16 + %74 = extractelement <4 x i32> %73, i64 0 + %75 = load <4 x i32>, ptr %ww, align 16 + %76 = extractelement <4 x i32> %75, i64 1 + %77 = load <4 x i32>, ptr %ww, align 16 + %78 = extractelement <4 x i32> %77, i64 2 + %79 = load <4 x i32>, ptr %ww, align 16 + %80 = extractelement <4 x i32> %79, i64 3 + %81 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %74, i32 %76, i32 %78, i32 %80) + %82 = load <4 x float>, ptr %y, align 16 + %83 = load <4 x float>, ptr %z, align 16 + %ge = fcmp oge <4 x float> %82, %83 + %84 = sext <4 x i1> %ge to <4 x i32> + store <4 x i32> %84, ptr %ww, align 16 + %85 = load <4 x i32>, ptr %ww, align 16 + %86 = extractelement <4 x i32> %85, i64 0 + %87 = load <4 x i32>, ptr %ww, align 16 + %88 = extractelement <4 x i32> %87, i64 1 + %89 = load <4 x i32>, ptr %ww, align 16 + %90 = extractelement <4 x i32> %89, i64 2 + %91 = load <4 x i32>, ptr %ww, align 16 + %92 = extractelement <4 x i32> %91, i64 3 + %93 = call i32 (ptr, ...) @printf(ptr @.str.9, i32 %86, i32 %88, i32 %90, i32 %92) + %94 = load <4 x float>, ptr %y, align 16 + %95 = load <4 x float>, ptr %z, align 16 + %eq = fcmp oeq <4 x float> %94, %95 + %96 = sext <4 x i1> %eq to <4 x i32> + store <4 x i32> %96, ptr %ww, align 16 + %97 = load <4 x i32>, ptr %ww, align 16 + %98 = extractelement <4 x i32> %97, i64 0 + %99 = load <4 x i32>, ptr %ww, align 16 + %100 = extractelement <4 x i32> %99, i64 1 + %101 = load <4 x i32>, ptr %ww, align 16 + %102 = extractelement <4 x i32> %101, i64 2 + %103 = load <4 x i32>, ptr %ww, align 16 + %104 = extractelement <4 x i32> %103, i64 3 + %105 = call i32 (ptr, ...) @printf(ptr @.str.10, i32 %98, i32 %100, i32 %102, i32 %104) + %106 = load <4 x float>, ptr %y, align 16 + %107 = load <4 x float>, ptr %z, align 16 + %neq = fcmp one <4 x float> %106, %107 + %108 = sext <4 x i1> %neq to <4 x i32> + store <4 x i32> %108, ptr %ww, align 16 + %109 = load <4 x i32>, ptr %ww, align 16 + %110 = extractelement <4 x i32> %109, i64 0 + %111 = load <4 x i32>, ptr %ww, align 16 + %112 = extractelement <4 x i32> %111, i64 1 + %113 = load <4 x i32>, ptr %ww, align 16 + %114 = extractelement <4 x i32> %113, i64 2 + %115 = load <4 x i32>, ptr %ww, align 16 + %116 = extractelement <4 x i32> %115, i64 3 + %117 = call i32 (ptr, ...) @printf(ptr @.str.11, i32 %110, i32 %112, i32 %114, i32 %116) + ret void +} + +; Function Attrs: nounwind +define void @test.testb() #0 { +entry: + %y = alloca <4 x i8>, align 4 + %z = alloca <4 x i8>, align 4 + %ww = alloca <4 x i8>, align 4 + store <4 x i8> , ptr %y, align 4 + store <4 x i8> , ptr %z, align 4 + %0 = load <4 x i8>, ptr %y, align 4 + %1 = load <4 x i8>, ptr %z, align 4 + %lt = icmp ult <4 x i8> %0, %1 + %2 = sext <4 x i1> %lt to <4 x i8> + store <4 x i8> %2, ptr %ww, align 4 + %3 = load <4 x i8>, ptr %ww, align 4 + %4 = extractelement <4 x i8> %3, i64 0 + %sisiext = sext i8 %4 to i32 + %5 = load <4 x i8>, ptr %ww, align 4 + %6 = extractelement <4 x i8> %5, i64 1 + %sisiext1 = sext i8 %6 to i32 + %7 = load <4 x i8>, ptr %ww, align 4 + %8 = extractelement <4 x i8> %7, i64 2 + %sisiext2 = sext i8 %8 to i32 + %9 = load <4 x i8>, ptr %ww, align 4 + %10 = extractelement <4 x i8> %9, i64 3 + %sisiext3 = sext i8 %10 to i32 + %11 = call i32 (ptr, ...) @printf(ptr @.str.12, i32 %sisiext, i32 %sisiext1, i32 %sisiext2, i32 %sisiext3) + %12 = load <4 x i8>, ptr %y, align 4 + %13 = load <4 x i8>, ptr %z, align 4 + %le = icmp ule <4 x i8> %12, %13 + %14 = sext <4 x i1> %le to <4 x i8> + store <4 x i8> %14, ptr %ww, align 4 + %15 = load <4 x i8>, ptr %ww, align 4 + %16 = extractelement <4 x i8> %15, i64 0 + %sisiext4 = sext i8 %16 to i32 + %17 = load <4 x i8>, ptr %ww, align 4 + %18 = extractelement <4 x i8> %17, i64 1 + %sisiext5 = sext i8 %18 to i32 + %19 = load <4 x i8>, ptr %ww, align 4 + %20 = extractelement <4 x i8> %19, i64 2 + %sisiext6 = sext i8 %20 to i32 + %21 = load <4 x i8>, ptr %ww, align 4 + %22 = extractelement <4 x i8> %21, i64 3 + %sisiext7 = sext i8 %22 to i32 + %23 = call i32 (ptr, ...) @printf(ptr @.str.13, i32 %sisiext4, i32 %sisiext5, i32 %sisiext6, i32 %sisiext7) + %24 = load <4 x i8>, ptr %y, align 4 + %25 = load <4 x i8>, ptr %z, align 4 + %gt = icmp ugt <4 x i8> %24, %25 + %26 = sext <4 x i1> %gt to <4 x i8> + store <4 x i8> %26, ptr %ww, align 4 + %27 = load <4 x i8>, ptr %ww, align 4 + %28 = extractelement <4 x i8> %27, i64 0 + %sisiext8 = sext i8 %28 to i32 + %29 = load <4 x i8>, ptr %ww, align 4 + %30 = extractelement <4 x i8> %29, i64 1 + %sisiext9 = sext i8 %30 to i32 + %31 = load <4 x i8>, ptr %ww, align 4 + %32 = extractelement <4 x i8> %31, i64 2 + %sisiext10 = sext i8 %32 to i32 + %33 = load <4 x i8>, ptr %ww, align 4 + %34 = extractelement <4 x i8> %33, i64 3 + %sisiext11 = sext i8 %34 to i32 + %35 = call i32 (ptr, ...) @printf(ptr @.str.14, i32 %sisiext8, i32 %sisiext9, i32 %sisiext10, i32 %sisiext11) + %36 = load <4 x i8>, ptr %y, align 4 + %37 = load <4 x i8>, ptr %z, align 4 + %ge = icmp uge <4 x i8> %36, %37 + %38 = sext <4 x i1> %ge to <4 x i8> + store <4 x i8> %38, ptr %ww, align 4 + %39 = load <4 x i8>, ptr %ww, align 4 + %40 = extractelement <4 x i8> %39, i64 0 + %sisiext12 = sext i8 %40 to i32 + %41 = load <4 x i8>, ptr %ww, align 4 + %42 = extractelement <4 x i8> %41, i64 1 + %sisiext13 = sext i8 %42 to i32 + %43 = load <4 x i8>, ptr %ww, align 4 + %44 = extractelement <4 x i8> %43, i64 2 + %sisiext14 = sext i8 %44 to i32 + %45 = load <4 x i8>, ptr %ww, align 4 + %46 = extractelement <4 x i8> %45, i64 3 + %sisiext15 = sext i8 %46 to i32 + %47 = call i32 (ptr, ...) @printf(ptr @.str.15, i32 %sisiext12, i32 %sisiext13, i32 %sisiext14, i32 %sisiext15) + %48 = load <4 x i8>, ptr %y, align 4 + %49 = load <4 x i8>, ptr %z, align 4 + %eq = icmp eq <4 x i8> %48, %49 + %50 = sext <4 x i1> %eq to <4 x i8> + store <4 x i8> %50, ptr %ww, align 4 + %51 = load <4 x i8>, ptr %ww, align 4 + %52 = extractelement <4 x i8> %51, i64 0 + %sisiext16 = sext i8 %52 to i32 + %53 = load <4 x i8>, ptr %ww, align 4 + %54 = extractelement <4 x i8> %53, i64 1 + %sisiext17 = sext i8 %54 to i32 + %55 = load <4 x i8>, ptr %ww, align 4 + %56 = extractelement <4 x i8> %55, i64 2 + %sisiext18 = sext i8 %56 to i32 + %57 = load <4 x i8>, ptr %ww, align 4 + %58 = extractelement <4 x i8> %57, i64 3 + %sisiext19 = sext i8 %58 to i32 + %59 = call i32 (ptr, ...) @printf(ptr @.str.16, i32 %sisiext16, i32 %sisiext17, i32 %sisiext18, i32 %sisiext19) + %60 = load <4 x i8>, ptr %y, align 4 + %61 = load <4 x i8>, ptr %z, align 4 + %neq = icmp ne <4 x i8> %60, %61 + %62 = sext <4 x i1> %neq to <4 x i8> + store <4 x i8> %62, ptr %ww, align 4 + %63 = load <4 x i8>, ptr %ww, align 4 + %64 = extractelement <4 x i8> %63, i64 0 + %sisiext20 = sext i8 %64 to i32 + %65 = load <4 x i8>, ptr %ww, align 4 + %66 = extractelement <4 x i8> %65, i64 1 + %sisiext21 = sext i8 %66 to i32 + %67 = load <4 x i8>, ptr %ww, align 4 + %68 = extractelement <4 x i8> %67, i64 2 + %sisiext22 = sext i8 %68 to i32 + %69 = load <4 x i8>, ptr %ww, align 4 + %70 = extractelement <4 x i8> %69, i64 3 + %sisiext23 = sext i8 %70 to i32 + %71 = call i32 (ptr, ...) @printf(ptr @.str.17, i32 %sisiext20, i32 %sisiext21, i32 %sisiext22, i32 %sisiext23) + ret void +} + +; Function Attrs: nounwind +define void @test.testi() #0 { +entry: + %y = alloca <4 x i32>, align 16 + %z = alloca <4 x i32>, align 16 + %w = alloca <4 x i32>, align 16 + %uz = alloca <4 x i32>, align 16 + store <4 x i32> , ptr %y, align 16 + store <4 x i32> , ptr %z, align 16 + %0 = load <4 x i32>, ptr %y, align 16 + %1 = load <4 x i32>, ptr %z, align 16 + %add = add <4 x i32> %0, %1 + store <4 x i32> %add, ptr %w, align 16 + %2 = load <4 x i32>, ptr %w, align 16 + %3 = extractelement <4 x i32> %2, i64 0 + %4 = load <4 x i32>, ptr %w, align 16 + %5 = extractelement <4 x i32> %4, i64 1 + %6 = load <4 x i32>, ptr %w, align 16 + %7 = extractelement <4 x i32> %6, i64 2 + %8 = load <4 x i32>, ptr %w, align 16 + %9 = extractelement <4 x i32> %8, i64 3 + %10 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %3, i32 %5, i32 %7, i32 %9) + %11 = load <4 x i32>, ptr %y, align 16 + %12 = load <4 x i32>, ptr %z, align 16 + %mul = mul <4 x i32> %11, %12 + store <4 x i32> %mul, ptr %w, align 16 + %13 = load <4 x i32>, ptr %w, align 16 + %14 = extractelement <4 x i32> %13, i64 0 + %15 = load <4 x i32>, ptr %w, align 16 + %16 = extractelement <4 x i32> %15, i64 1 + %17 = load <4 x i32>, ptr %w, align 16 + %18 = extractelement <4 x i32> %17, i64 2 + %19 = load <4 x i32>, ptr %w, align 16 + %20 = extractelement <4 x i32> %19, i64 3 + %21 = call i32 (ptr, ...) @printf(ptr @.str.19, i32 %14, i32 %16, i32 %18, i32 %20) + %22 = load <4 x i32>, ptr %y, align 16 + %23 = load <4 x i32>, ptr %z, align 16 + %24 = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %23) + %zero = icmp eq i32 %24, 0 + br i1 %zero, label %panic, label %checkok + +panic: ; preds = %entry + call void @"std::core::builtin.panic"(ptr @.zstr.20, ptr @.zstr.21, ptr @.zstr.22, i32 56) + br label %checkok + +checkok: ; preds = %panic, %entry + %sdiv = sdiv <4 x i32> %22, %23 + store <4 x i32> %sdiv, ptr %w, align 16 + %25 = load <4 x i32>, ptr %w, align 16 + %26 = extractelement <4 x i32> %25, i64 0 + %27 = load <4 x i32>, ptr %w, align 16 + %28 = extractelement <4 x i32> %27, i64 1 + %29 = load <4 x i32>, ptr %w, align 16 + %30 = extractelement <4 x i32> %29, i64 2 + %31 = load <4 x i32>, ptr %w, align 16 + %32 = extractelement <4 x i32> %31, i64 3 + %33 = call i32 (ptr, ...) @printf(ptr @.str.23, i32 %26, i32 %28, i32 %30, i32 %32) + %34 = load <4 x i32>, ptr %y, align 16 + %35 = load <4 x i32>, ptr %z, align 16 + %sub = sub <4 x i32> %34, %35 + store <4 x i32> %sub, ptr %w, align 16 + %36 = load <4 x i32>, ptr %w, align 16 + %37 = extractelement <4 x i32> %36, i64 0 + %38 = load <4 x i32>, ptr %w, align 16 + %39 = extractelement <4 x i32> %38, i64 1 + %40 = load <4 x i32>, ptr %w, align 16 + %41 = extractelement <4 x i32> %40, i64 2 + %42 = load <4 x i32>, ptr %w, align 16 + %43 = extractelement <4 x i32> %42, i64 3 + %44 = call i32 (ptr, ...) @printf(ptr @.str.24, i32 %37, i32 %39, i32 %41, i32 %43) + %45 = load <4 x i32>, ptr %z, align 16 + %46 = load <4 x i32>, ptr %y, align 16 + %47 = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> %46) + %shift_underflow = icmp slt i32 %47, 0 + br i1 %shift_underflow, label %panic1, label %checkok2 + +panic1: ; preds = %checkok + call void @"std::core::builtin.panic"(ptr @.zstr.25, ptr @.zstr.26, ptr @.zstr.27, i32 60) + br label %checkok2 + +checkok2: ; preds = %panic1, %checkok + %48 = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> %46) + %shift_exceeds = icmp sge i32 %48, 32 + br i1 %shift_exceeds, label %panic3, label %checkok4 + +panic3: ; preds = %checkok2 + call void @"std::core::builtin.panic"(ptr @.zstr.28, ptr @.zstr.29, ptr @.zstr.30, i32 60) + br label %checkok4 + +checkok4: ; preds = %panic3, %checkok2 + %ashr = ashr <4 x i32> %45, %46 + %49 = freeze <4 x i32> %ashr + store <4 x i32> %49, ptr %w, align 16 + %50 = load <4 x i32>, ptr %w, align 16 + %51 = extractelement <4 x i32> %50, i64 0 + %52 = load <4 x i32>, ptr %w, align 16 + %53 = extractelement <4 x i32> %52, i64 1 + %54 = load <4 x i32>, ptr %w, align 16 + %55 = extractelement <4 x i32> %54, i64 2 + %56 = load <4 x i32>, ptr %w, align 16 + %57 = extractelement <4 x i32> %56, i64 3 + %58 = call i32 (ptr, ...) @printf(ptr @.str.31, i32 %51, i32 %53, i32 %55, i32 %57) + %59 = load <4 x i32>, ptr %z, align 16 + %60 = load <4 x i32>, ptr %y, align 16 + %61 = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> %60) + %shift_underflow5 = icmp slt i32 %61, 0 + br i1 %shift_underflow5, label %panic6, label %checkok7 + +panic6: ; preds = %checkok4 + call void @"std::core::builtin.panic"(ptr @.zstr.32, ptr @.zstr.33, ptr @.zstr.34, i32 62) + br label %checkok7 + +checkok7: ; preds = %panic6, %checkok4 + %62 = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> %60) + %shift_exceeds8 = icmp sge i32 %62, 32 + br i1 %shift_exceeds8, label %panic9, label %checkok10 + +panic9: ; preds = %checkok7 + call void @"std::core::builtin.panic"(ptr @.zstr.35, ptr @.zstr.36, ptr @.zstr.37, i32 62) + br label %checkok10 + +checkok10: ; preds = %panic9, %checkok7 + %shl = shl <4 x i32> %59, %60 + %63 = freeze <4 x i32> %shl + store <4 x i32> %63, ptr %w, align 16 + %64 = load <4 x i32>, ptr %w, align 16 + %65 = extractelement <4 x i32> %64, i64 0 + %66 = load <4 x i32>, ptr %w, align 16 + %67 = extractelement <4 x i32> %66, i64 1 + %68 = load <4 x i32>, ptr %w, align 16 + %69 = extractelement <4 x i32> %68, i64 2 + %70 = load <4 x i32>, ptr %w, align 16 + %71 = extractelement <4 x i32> %70, i64 3 + %72 = call i32 (ptr, ...) @printf(ptr @.str.38, i32 %65, i32 %67, i32 %69, i32 %71) + %73 = load <4 x i32>, ptr %z, align 16 + %74 = load <4 x i32>, ptr %y, align 16 + %gt = icmp sgt <4 x i32> %73, %74 + %75 = sext <4 x i1> %gt to <4 x i32> + store <4 x i32> %75, ptr %w, align 16 + %76 = load <4 x i32>, ptr %w, align 16 + %77 = extractelement <4 x i32> %76, i64 0 + %78 = load <4 x i32>, ptr %w, align 16 + %79 = extractelement <4 x i32> %78, i64 1 + %80 = load <4 x i32>, ptr %w, align 16 + %81 = extractelement <4 x i32> %80, i64 2 + %82 = load <4 x i32>, ptr %w, align 16 + %83 = extractelement <4 x i32> %82, i64 3 + %84 = call i32 (ptr, ...) @printf(ptr @.str.39, i32 %77, i32 %79, i32 %81, i32 %83) + %85 = load <4 x i32>, ptr %z, align 16 + %86 = load <4 x i32>, ptr %y, align 16 + %ge = icmp sge <4 x i32> %85, %86 + %87 = sext <4 x i1> %ge to <4 x i32> + store <4 x i32> %87, ptr %w, align 16 + %88 = load <4 x i32>, ptr %w, align 16 + %89 = extractelement <4 x i32> %88, i64 0 + %90 = load <4 x i32>, ptr %w, align 16 + %91 = extractelement <4 x i32> %90, i64 1 + %92 = load <4 x i32>, ptr %w, align 16 + %93 = extractelement <4 x i32> %92, i64 2 + %94 = load <4 x i32>, ptr %w, align 16 + %95 = extractelement <4 x i32> %94, i64 3 + %96 = call i32 (ptr, ...) @printf(ptr @.str.40, i32 %89, i32 %91, i32 %93, i32 %95) + %97 = load <4 x i32>, ptr %z, align 16 + %98 = load <4 x i32>, ptr %y, align 16 + %lt = icmp slt <4 x i32> %97, %98 + %99 = sext <4 x i1> %lt to <4 x i32> + store <4 x i32> %99, ptr %w, align 16 + %100 = load <4 x i32>, ptr %w, align 16 + %101 = extractelement <4 x i32> %100, i64 0 + %102 = load <4 x i32>, ptr %w, align 16 + %103 = extractelement <4 x i32> %102, i64 1 + %104 = load <4 x i32>, ptr %w, align 16 + %105 = extractelement <4 x i32> %104, i64 2 + %106 = load <4 x i32>, ptr %w, align 16 + %107 = extractelement <4 x i32> %106, i64 3 + %108 = call i32 (ptr, ...) @printf(ptr @.str.41, i32 %101, i32 %103, i32 %105, i32 %107) + %109 = load <4 x i32>, ptr %z, align 16 + %110 = load <4 x i32>, ptr %y, align 16 + %le = icmp sle <4 x i32> %109, %110 + %111 = sext <4 x i1> %le to <4 x i32> + store <4 x i32> %111, ptr %w, align 16 + %112 = load <4 x i32>, ptr %w, align 16 + %113 = extractelement <4 x i32> %112, i64 0 + %114 = load <4 x i32>, ptr %w, align 16 + %115 = extractelement <4 x i32> %114, i64 1 + %116 = load <4 x i32>, ptr %w, align 16 + %117 = extractelement <4 x i32> %116, i64 2 + %118 = load <4 x i32>, ptr %w, align 16 + %119 = extractelement <4 x i32> %118, i64 3 + %120 = call i32 (ptr, ...) @printf(ptr @.str.42, i32 %113, i32 %115, i32 %117, i32 %119) + %121 = load <4 x i32>, ptr %z, align 16 + %122 = load <4 x i32>, ptr %y, align 16 + %eq = icmp eq <4 x i32> %121, %122 + %123 = sext <4 x i1> %eq to <4 x i32> + store <4 x i32> %123, ptr %w, align 16 + %124 = load <4 x i32>, ptr %w, align 16 + %125 = extractelement <4 x i32> %124, i64 0 + %126 = load <4 x i32>, ptr %w, align 16 + %127 = extractelement <4 x i32> %126, i64 1 + %128 = load <4 x i32>, ptr %w, align 16 + %129 = extractelement <4 x i32> %128, i64 2 + %130 = load <4 x i32>, ptr %w, align 16 + %131 = extractelement <4 x i32> %130, i64 3 + %132 = call i32 (ptr, ...) @printf(ptr @.str.43, i32 %125, i32 %127, i32 %129, i32 %131) + %133 = load <4 x i32>, ptr %z, align 16 + %134 = load <4 x i32>, ptr %y, align 16 + %neq = icmp ne <4 x i32> %133, %134 + %135 = sext <4 x i1> %neq to <4 x i32> + store <4 x i32> %135, ptr %w, align 16 + %136 = load <4 x i32>, ptr %w, align 16 + %137 = extractelement <4 x i32> %136, i64 0 + %138 = load <4 x i32>, ptr %w, align 16 + %139 = extractelement <4 x i32> %138, i64 1 + %140 = load <4 x i32>, ptr %w, align 16 + %141 = extractelement <4 x i32> %140, i64 2 + %142 = load <4 x i32>, ptr %w, align 16 + %143 = extractelement <4 x i32> %142, i64 3 + %144 = call i32 (ptr, ...) @printf(ptr @.str.44, i32 %137, i32 %139, i32 %141, i32 %143) + store <4 x i32> , ptr %uz, align 16 + %145 = load <4 x i32>, ptr %uz, align 16 + %146 = load <4 x i32>, ptr %y, align 16 + %lt11 = icmp slt <4 x i32> %146, %145 + %check = icmp slt <4 x i32> %145, zeroinitializer + %siui-lt = or <4 x i1> %check, %lt11 + %147 = sext <4 x i1> %siui-lt to <4 x i32> + store <4 x i32> %147, ptr %w, align 16 + %148 = load <4 x i32>, ptr %w, align 16 + %149 = extractelement <4 x i32> %148, i64 0 + %150 = load <4 x i32>, ptr %w, align 16 + %151 = extractelement <4 x i32> %150, i64 1 + %152 = load <4 x i32>, ptr %w, align 16 + %153 = extractelement <4 x i32> %152, i64 2 + %154 = load <4 x i32>, ptr %w, align 16 + %155 = extractelement <4 x i32> %154, i64 3 + %156 = call i32 (ptr, ...) @printf(ptr @.str.45, i32 %149, i32 %151, i32 %153, i32 %155) + %157 = load <4 x i32>, ptr %uz, align 16 + %158 = load <4 x i32>, ptr %y, align 16 + %le12 = icmp sle <4 x i32> %158, %157 + %check13 = icmp slt <4 x i32> %157, zeroinitializer + %siui-le = or <4 x i1> %check13, %le12 + %159 = sext <4 x i1> %siui-le to <4 x i32> + store <4 x i32> %159, ptr %w, align 16 + %160 = load <4 x i32>, ptr %w, align 16 + %161 = extractelement <4 x i32> %160, i64 0 + %162 = load <4 x i32>, ptr %w, align 16 + %163 = extractelement <4 x i32> %162, i64 1 + %164 = load <4 x i32>, ptr %w, align 16 + %165 = extractelement <4 x i32> %164, i64 2 + %166 = load <4 x i32>, ptr %w, align 16 + %167 = extractelement <4 x i32> %166, i64 3 + %168 = call i32 (ptr, ...) @printf(ptr @.str.46, i32 %161, i32 %163, i32 %165, i32 %167) + %169 = load <4 x i32>, ptr %uz, align 16 + %170 = load <4 x i32>, ptr %y, align 16 + %gt14 = icmp sgt <4 x i32> %170, %169 + %check15 = icmp sge <4 x i32> %169, zeroinitializer + %siui-gt = and <4 x i1> %check15, %gt14 + %171 = sext <4 x i1> %siui-gt to <4 x i32> + store <4 x i32> %171, ptr %w, align 16 + %172 = load <4 x i32>, ptr %w, align 16 + %173 = extractelement <4 x i32> %172, i64 0 + %174 = load <4 x i32>, ptr %w, align 16 + %175 = extractelement <4 x i32> %174, i64 1 + %176 = load <4 x i32>, ptr %w, align 16 + %177 = extractelement <4 x i32> %176, i64 2 + %178 = load <4 x i32>, ptr %w, align 16 + %179 = extractelement <4 x i32> %178, i64 3 + %180 = call i32 (ptr, ...) @printf(ptr @.str.47, i32 %173, i32 %175, i32 %177, i32 %179) + %181 = load <4 x i32>, ptr %uz, align 16 + %182 = load <4 x i32>, ptr %y, align 16 + %ge16 = icmp sge <4 x i32> %182, %181 + %check17 = icmp sge <4 x i32> %181, zeroinitializer + %siui-ge = and <4 x i1> %check17, %ge16 + %183 = sext <4 x i1> %siui-ge to <4 x i32> + store <4 x i32> %183, ptr %w, align 16 + %184 = load <4 x i32>, ptr %w, align 16 + %185 = extractelement <4 x i32> %184, i64 0 + %186 = load <4 x i32>, ptr %w, align 16 + %187 = extractelement <4 x i32> %186, i64 1 + %188 = load <4 x i32>, ptr %w, align 16 + %189 = extractelement <4 x i32> %188, i64 2 + %190 = load <4 x i32>, ptr %w, align 16 + %191 = extractelement <4 x i32> %190, i64 3 + %192 = call i32 (ptr, ...) @printf(ptr @.str.48, i32 %185, i32 %187, i32 %189, i32 %191) + %193 = load <4 x i32>, ptr %uz, align 16 + %194 = load <4 x i32>, ptr %y, align 16 + %eq18 = icmp eq <4 x i32> %194, %193 + %check19 = icmp sge <4 x i32> %194, zeroinitializer + %siui-eq = and <4 x i1> %check19, %eq18 + %195 = sext <4 x i1> %siui-eq to <4 x i32> + store <4 x i32> %195, ptr %w, align 16 + %196 = load <4 x i32>, ptr %w, align 16 + %197 = extractelement <4 x i32> %196, i64 0 + %198 = load <4 x i32>, ptr %w, align 16 + %199 = extractelement <4 x i32> %198, i64 1 + %200 = load <4 x i32>, ptr %w, align 16 + %201 = extractelement <4 x i32> %200, i64 2 + %202 = load <4 x i32>, ptr %w, align 16 + %203 = extractelement <4 x i32> %202, i64 3 + %204 = call i32 (ptr, ...) @printf(ptr @.str.49, i32 %197, i32 %199, i32 %201, i32 %203) + %205 = load <4 x i32>, ptr %uz, align 16 + %206 = load <4 x i32>, ptr %y, align 16 + %neq20 = icmp ne <4 x i32> %206, %205 + %check21 = icmp slt <4 x i32> %206, zeroinitializer + %siui-ne = or <4 x i1> %check21, %neq20 + %207 = sext <4 x i1> %siui-ne to <4 x i32> + store <4 x i32> %207, ptr %w, align 16 + %208 = load <4 x i32>, ptr %w, align 16 + %209 = extractelement <4 x i32> %208, i64 0 + %210 = load <4 x i32>, ptr %w, align 16 + %211 = extractelement <4 x i32> %210, i64 1 + %212 = load <4 x i32>, ptr %w, align 16 + %213 = extractelement <4 x i32> %212, i64 2 + %214 = load <4 x i32>, ptr %w, align 16 + %215 = extractelement <4 x i32> %214, i64 3 + %216 = call i32 (ptr, ...) @printf(ptr @.str.50, i32 %209, i32 %211, i32 %213, i32 %215) + ret void +} diff --git a/test/test_suite2/vector/vector_to_array_cast.c3t b/test/test_suite2/vector/vector_to_array_cast.c3t new file mode 100644 index 000000000..03e226515 --- /dev/null +++ b/test/test_suite2/vector/vector_to_array_cast.c3t @@ -0,0 +1,38 @@ +// #target: macos-x64 + +module test; + +int[<2>] b = (int[<2>])(int[2] { 1, 2 }); +int[2] c = (int[2])(int[<2>] { 1, 2 }); + +fn void tester() +{ + int[<2>] x = { 1, 2 }; + int[2] y = (int[2])(x); + x = (int[<2>])(y); +} + +/* #expect: test.ll + +@test.b = local_unnamed_addr global <2 x i32> , align 8 +@test.c = local_unnamed_addr global [2 x i32] [i32 1, i32 2], align 4 + +define void @test.tester() #0 { +entry: + %x = alloca <2 x i32>, align 8 + %y = alloca [2 x i32], align 4 + store <2 x i32> , ptr %x, align 8 + %0 = load <2 x i32>, ptr %x, align 8 + %1 = extractelement <2 x i32> %0, i64 0 + %2 = insertvalue [2 x i32] undef, i32 %1, 0 + %3 = extractelement <2 x i32> %0, i64 1 + %4 = insertvalue [2 x i32] %2, i32 %3, 1 + store [2 x i32] %4, ptr %y, align 4 + %5 = load [2 x i32], ptr %y, align 4 + %6 = extractvalue [2 x i32] %5, 0 + %7 = insertelement <2 x i32> undef, i32 %6, i64 0 + %8 = extractvalue [2 x i32] %5, 1 + %9 = insertelement <2 x i32> %7, i32 %8, i64 1 + store <2 x i32> %9, ptr %x, align 8 + ret void +} diff --git a/test/test_suite2/visibility/ambiguous_var.c3t b/test/test_suite2/visibility/ambiguous_var.c3t new file mode 100644 index 000000000..dfad51ace --- /dev/null +++ b/test/test_suite2/visibility/ambiguous_var.c3t @@ -0,0 +1,27 @@ +// #file: file1.c3 +module foo; + +int a; +int b; + +// #file: file2.c3 +module bar; +int a; +int b; + +// #file: file3.c3 + +module baz; +import foo; +import bar; + +int a; + +private fn void test2() +{ + int c = a; // This is fine. + c = foo::b; + c = bar::b; + c = foo::a; + c = b; // #error: global variable 'b' is defined in both 'foo' and 'bar', please use either foo::b or bar::b to resolve the ambiguity +} diff --git a/test/test_suite2/visibility/no_shared_imports.c3t b/test/test_suite2/visibility/no_shared_imports.c3t new file mode 100644 index 000000000..420d4410c --- /dev/null +++ b/test/test_suite2/visibility/no_shared_imports.c3t @@ -0,0 +1,23 @@ +// #file: file1.c3 +module baz; + +fn void runBar() +{ + visible(); + bar::barFunc(); // #error: 'bar::barFunc' could not be found, did you spell it right? +} + +// #file: file2.c3 +module baz; +import private bar; + +private fn void visible() +{ + bar::barFunc(); +} + +// #file: file3.c3 +module bar; + +private fn void barFunc() +{} \ No newline at end of file diff --git a/test/test_suite2/visibility/not_visible.c3t b/test/test_suite2/visibility/not_visible.c3t new file mode 100644 index 000000000..30aa271fa --- /dev/null +++ b/test/test_suite2/visibility/not_visible.c3t @@ -0,0 +1,16 @@ +// #file: file1.c3 +module baz; +import bar; + +fn void runBar() +{ + bar::notVisible(); // #error: 'bar::notVisible' is not visible from this module. +} + +// #file: file2.c3 +module bar; + +private fn void notVisible() +{ + +} \ No newline at end of file diff --git a/test/test_suite2/visibility/private_import.c3 b/test/test_suite2/visibility/private_import.c3 new file mode 100644 index 000000000..32360a4c6 --- /dev/null +++ b/test/test_suite2/visibility/private_import.c3 @@ -0,0 +1,21 @@ +module foo; + +private fn void hidden() +{ +} + +module bar; +import foo; + +fn void test() +{ + foo::hidden(); // #error: The function 'foo::hidden' is not visible from this module. +} + +module baz; +import private foo; + +fn void test() +{ + foo::hidden(); +} \ No newline at end of file diff --git a/test/test_suite2/visibility/private_module.c3 b/test/test_suite2/visibility/private_module.c3 new file mode 100644 index 000000000..5faba9b0b --- /dev/null +++ b/test/test_suite2/visibility/private_module.c3 @@ -0,0 +1,17 @@ +module private foo; + +fn void hidden() +{ +} + +module bar; +import foo; // #error: Importing a private module is not allowed (unless 'import private' is used). + + +module baz; +import private foo; + +fn void test() +{ + foo::hidden(); +} \ No newline at end of file diff --git a/test/test_suite2/visibility/shared_module.c3t b/test/test_suite2/visibility/shared_module.c3t new file mode 100644 index 000000000..3895bec2a --- /dev/null +++ b/test/test_suite2/visibility/shared_module.c3t @@ -0,0 +1,15 @@ +// #file: file1.c3 +module baz; + +fn void runBar() +{ + visible(); +} + +// #file: file2.c3 +module baz; + +private fn void visible() +{ + +} \ No newline at end of file diff --git a/test/test_suite2/visibility/simple_visibility.c3t b/test/test_suite2/visibility/simple_visibility.c3t new file mode 100644 index 000000000..a88afec45 --- /dev/null +++ b/test/test_suite2/visibility/simple_visibility.c3t @@ -0,0 +1,16 @@ +// #file: file1.c3 +module baz; +import bar; + +fn void runBar() +{ + bar::visible(); +} + +// #file: file2.c3 +module bar; + +fn void visible() +{ + +}